package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.dao.PaasFormExplainDao;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.subform.TransferSubFormHelper;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.pojo.dto.JxcStockDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.script.help.ScriptEsHelper;
import com.xbongbong.paas.script.pojo.ListVO;
import com.xbongbong.paas.script.pojo.ProductUserComparePojo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.flowbill.dto.FlowBillInsertDTO;
import com.xbongbong.pro.script.pojo.dto.ProductDTO;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.dao.ProductStockDao;
import com.xbongbong.saas.domain.dao.ProductUserDao;
import com.xbongbong.saas.domain.entity.AssembleProductEntity;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductSerialBalanceEntity;
import com.xbongbong.saas.domain.entity.ProductSerialFlowEntity;
import com.xbongbong.saas.domain.entity.ProductStockEntity;
import com.xbongbong.saas.domain.entity.ProductUserEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.PurchaseBalanceEntity;
import com.xbongbong.saas.domain.entity.PurchaseProductEntity;
import com.xbongbong.saas.domain.entity.ReturnedPurchaseProductEntity;
import com.xbongbong.saas.domain.entity.SmartReplenishmentEntity;
import com.xbongbong.saas.domain.entity.SpecificationEntity;
import com.xbongbong.saas.domain.entity.WarehouseOristockEntity;
import com.xbongbong.saas.domain.entity.WarehouseOristockProductEntity;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.WorkOrderProductEntity;
import com.xbongbong.saas.domain.entity.ext.AssembleEntityExt;
import com.xbongbong.saas.domain.entity.ext.InstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.PurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.RefundEntityExt;
import com.xbongbong.saas.domain.entity.ext.ReturnedPurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.WarehouseEntityExt;
import com.xbongbong.saas.enums.ContractProduceEnum;
import com.xbongbong.saas.enums.ForbiddenSettingEnum;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.AssembleEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ContractOutstockEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.business.WaitOutStockStatusEnum;
import com.xbongbong.saas.enums.dictionary.AllOutBoundEnum;
import com.xbongbong.saas.enums.dictionary.ArchivedEnum;
import com.xbongbong.saas.enums.dictionary.ShipStatusEnum;
import com.xbongbong.saas.enums.product.PurchaseProductEnum;
import com.xbongbong.saas.enums.subform.ProductStockSubFormEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.model.AssembleModel;
import com.xbongbong.saas.model.AssembleProductModel;
import com.xbongbong.saas.model.BatchFlowBillModel;
import com.xbongbong.saas.model.BatchSurplusRecordModel;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductSerialBalanceModel;
import com.xbongbong.saas.model.ProductSerialFlowModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.model.ProductUserModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.PurchaseBalanceModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.PurchaseProductModel;
import com.xbongbong.saas.model.RefundModel;
import com.xbongbong.saas.model.ReturnedPurchaseModel;
import com.xbongbong.saas.model.ReturnedPurchaseProductModel;
import com.xbongbong.saas.model.SmartReplenishmentModel;
import com.xbongbong.saas.model.SpecificationModel;
import com.xbongbong.saas.model.StockFlowBillModel;
import com.xbongbong.saas.model.StockSurplusRecordModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.model.WarehouseOristockModel;
import com.xbongbong.saas.model.WarehouseOristockProductModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.model.WorkOrderProductModel;
import com.xbongbong.saas.script.help.InitExplainsHelper;
import com.xbongbong.saas.service.BatchFlowBillService;
import com.xbongbong.saas.service.StockFlowBillService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.constant.PaasFormTableNameConstant;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 应用模块名称<p>
 * 代码描述<p>
 * Company: 逍邦网络科技有限公司<p>
 *
 * @author chenshan
 * @version v1.0
 * @since 2019-11-25 14:33
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX+"/script/fixJxc")
public class JxcFixDataController {
    private static final Logger LOG = LoggerFactory.getLogger(JxcFixDataController.class);
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private EsHelper esHelper;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private ScriptEsHelper scriptEsHelper;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private ProductModel productModel;
    @Resource
    private ProductUserModel productUserModel;
    @Resource
    private ProductUserDao productUserDao;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private WarehouseOristockModel warehouseOristockModel;
    @Resource
    private WarehouseOristockProductModel warehouseOristockProductModel;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private WorkOrderProductModel workOrderProductModel;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private PurchaseProductModel purchaseProductModel;
    @Resource
    private ReturnedPurchaseProductModel returnedPurchaseProductModel;
    @Resource
    private ReturnedPurchaseModel returnedPurchaseModel;
    @Resource
    private AssembleProductModel assembleProductModel;
    @Resource
    private AssembleModel assembleModel;
    @Resource
    private ProductStockModel productStockModel;
    @Resource
    private TransferSubFormHelper transferSubFormHelper;
    @Resource
    private SpecificationModel specificationModel;
    @Resource
    private ProductSerialBalanceModel productSerialBalanceModel;
    @Resource
    private ProductStockDao productStockDao;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private SmartReplenishmentModel smartReplenishmentModel;
    @Resource
    private PurchaseBalanceModel purchaseBalanceModel;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private BatchFlowBillModel batchFlowBillModel;
    @Resource
    private BatchSurplusRecordModel batchSurplusRecordModel;
    @Resource
    private StockFlowBillModel stockFlowBillModel;
    @Resource
    private StockSurplusRecordModel stockSurplusRecordModel;
    @Resource
    private StockFlowBillService stockFlowBillService;
    @Resource
    private BatchFlowBillService batchFlowBillService;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private ContractModel contractModel;
    @Resource
    private PaasFormExplainDao paasFormExplainDao;
    @Resource
    private RefundModel refundModel;
    @Resource
    private ProductSerialFlowModel productSerialFlowModel;

    /**
     * 修复某个公司(某个产品)的所有库存信息:sku、productWarehouse
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixAllStock", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixAllStock(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (Objects.isNull(corpidList) || corpidList.size() != 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,"只允许刷一个公司");
        }
        if (Objects.isNull(fixDataJobDTO.getDataIdList())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,"dataIdList不需要也至少传个空数组");
        }
        LOG.warn("fixAllStock begin");
        String corpid = corpidList.get(0);
        //0普通模式，不过滤出入库产品，不插入分仓数据；1高级模式，过滤出入库产品，插入未匹配到的分仓数据
        Boolean superType = Objects.equals(fixDataJobDTO.getType(),1);
        Long idGte = 0L;
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,corpid);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        List<WarehouseEntityExt> warehouseEntityExtList = warehouseModel.findEntitys(param);
        List<Long> warehouseIdList = new ArrayList<>();
        warehouseEntityExtList.forEach(item -> warehouseIdList.add(item.getId()));
        warehouseIdList.add(-1L);
        while (true) {
            param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            if (!fixDataJobDTO.getDataIdList().isEmpty()) {
                param.put("idIn",fixDataJobDTO.getDataIdList());
            }
            param.put("dataParentIdGte",0L);
            param.put("idGte",idGte);
            param.put("pageSize",1000);
            param.put("orderByStr","id asc");
            List<ProductEntityExt> productEntityExtList = productModel.findEntitys(param);
            if (productEntityExtList.isEmpty()) {
                if (idGte <= 0L){
                    LOG.warn(JSONObject.toJSONString(param));
                    return "When I put a question mark, it is not that I have a problem, but I think you have a problem.";
                }
                break;
            }
            LOG.warn("idGte:" + idGte);
            idGte = productEntityExtList.get(productEntityExtList.size()-1).getId();
            Map<Long,PaasFormDataEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> productIdList = new ArrayList<>();
            productEntityExtList.forEach(item -> {
                productIdList.add(item.getId());
                if (superType) {
                    productMap.put(item.getId(), item);
                }
            });
            //入库
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid",corpid);
            map.put("productIdIn",productIdList);
            map.put("warehouseIdIn",warehouseIdList);
            map.put("del",0);
            List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(map);
            List<Long> idList = new ArrayList<>();
            if (!instockProductEntityList.isEmpty()) {
                List<Long> instockIdList = new ArrayList<>();
                instockProductEntityList.forEach(item -> instockIdList.add(item.getIntoWarehouseId()));
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", instockIdList);
                filterMap.put("del", 0);
                idList = instockModel.findIds(filterMap);
            }
            // 去掉在新建进工作流的数据，这个时候，库存不能进行运算
            removeAddData(idList, corpid);
            Map<Long,Double> skuStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String,Double>  productWarehouseStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (InstockProductEntity entity : instockProductEntityList){
                if (!idList.contains(entity.getIntoWarehouseId())){
                    continue;
                }
                //sku
                Double skuStock = skuStockMap.getOrDefault(entity.getProductId(),0D);
                skuStock = Arith.add(skuStock,entity.getProductNum());
                skuStockMap.put(entity.getProductId(),skuStock);
                //productWarehouse
                String key = entity.getProductId() + "_" + entity.getWarehouseId();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                productWarehouseStock = Arith.add(productWarehouseStock,entity.getProductNum());
                productWarehouseStockMap.put(key,productWarehouseStock);
            }
            //出库
            List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(map);
            idList = new ArrayList<>();
            if (!outstockProductEntityList.isEmpty()) {
                List<Long> outstockIdList = new ArrayList<>();
                outstockProductEntityList.forEach(item -> outstockIdList.add(item.getOutWarehouseId()));
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", outstockIdList);
                filterMap.put("del", 0);
                idList = outstockModel.findIds(filterMap);
            }
            // 去掉在新建进工作流的数据，这个时候，库存不能进行运算
            removeAddData(idList, corpid);
            for (OutstockProductEntity entity : outstockProductEntityList){
                if (!idList.contains(entity.getOutWarehouseId())){
                    continue;
                }
                //sku
                Double skuStock = skuStockMap.getOrDefault(entity.getProductId(),0D);
                skuStock = Arith.sub(skuStock,entity.getProductNum());
                skuStockMap.put(entity.getProductId(),skuStock);
                //productWarehouse
                String key = entity.getProductId() + "_" + entity.getWarehouseId();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                productWarehouseStock = Arith.sub(productWarehouseStock,entity.getProductNum());
                productWarehouseStockMap.put(key,productWarehouseStock);
            }
            param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            List<WarehouseOristockEntity> warehouseOristockEntityList = warehouseOristockModel.findEntitys(param);
            List<Long> oriWarehouseIdList = new ArrayList<>();
            Map<Long,Long> oriWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            warehouseOristockEntityList.forEach(item -> {
                oriWarehouseMap.put(item.getId().longValue(),item.getWarehouseId());
                oriWarehouseIdList.add(item.getWarehouseId());
            });
            param.put("oriStockIdIn",oriWarehouseMap.keySet());
            param.put("productIdIn",productIdList);
            List<WarehouseOristockProductEntity> warehouseOristockProductEntityList = warehouseOristockProductModel.findEntitys(param);
            for (WarehouseOristockProductEntity warehouseOristockProductEntity : warehouseOristockProductEntityList) {
                if (oriWarehouseMap.containsKey(warehouseOristockProductEntity.getOristockId().longValue())){
                    Long warehouseId = oriWarehouseMap.get(warehouseOristockProductEntity.getOristockId().longValue());
                    // 分仓库存
                    String key = warehouseOristockProductEntity.getProductId() + "_" + warehouseId;
                    Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                    productWarehouseStock = Arith.add(productWarehouseStock,warehouseOristockProductEntity.getOristockNum());
                    productWarehouseStockMap.put(key,productWarehouseStock);
                    // sku库存
                    Double skuStock = skuStockMap.getOrDefault(warehouseOristockProductEntity.getProductId(),0D);
                    skuStock = Arith.add(skuStock,warehouseOristockProductEntity.getOristockNum());
                    skuStockMap.put(warehouseOristockProductEntity.getProductId(),skuStock);
                }
            }
            //分仓
            param.clear();
            param.put("corpid",corpid);
            param.put("productIdIn",productIdList);
            param.put("warehouseChecked",1);
            param.put("del",0);
            param.put("columns","corpid,id,product_id,warehouse_id,cost,ori_num");
            List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(param,1);
            List<ProductWarehouseEntity> updateProductWareouseList = new ArrayList<>();
            Iterator<ProductWarehouseEntity> iterator = productWarehouseEntityList.iterator();
            //由于可能有老期初，同时又有全仓记录，先循环分仓记录，兼容老期初，再更新全仓记录
            while (iterator.hasNext()) {
                ProductWarehouseEntity entity = iterator.next();
                if (!Objects.equals(entity.getWarehouseId(),0L)){
                    String key = entity.getProductId() + "_" + entity.getWarehouseId();
                    if (entity.getOriNum() > 0 && !oriWarehouseIdList.contains(entity.getWarehouseId())) {
                        //老期初
                        Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                        productWarehouseStock = Arith.add(productWarehouseStock,entity.getOriNum());
                        productWarehouseStockMap.put(key,productWarehouseStock);

                        Double skuStock = skuStockMap.getOrDefault(entity.getProductId(),0D);
                        skuStock = Arith.add(skuStock,entity.getOriNum());
                        skuStockMap.put(entity.getProductId(),skuStock);
                    }
                    if (productWarehouseStockMap.containsKey(key)){
                        if (Objects.equals(entity.getNum(), productWarehouseStockMap.get(key))) {
                            iterator.remove();
                            productWarehouseStockMap.remove(key);
                            continue;
                        }
                        entity.setNum(productWarehouseStockMap.get(key));
                        productWarehouseStockMap.remove(key);
                    }else {
                        entity.setNum(0D);
                    }
                    updateProductWareouseList.add(entity);
                    iterator.remove();
                }
            }
            //全仓记录
            for (ProductWarehouseEntity entity : productWarehouseEntityList){
                if (Objects.equals(entity.getWarehouseId(),0L)){
                    if (Objects.equals(entity.getNum(), skuStockMap.get(entity.getProductId()))) {
                        continue;
                    }
                    entity.setNum(skuStockMap.getOrDefault(entity.getProductId(),0D));
                    updateProductWareouseList.add(entity);
                }
            }
            if (!updateProductWareouseList.isEmpty()){
                productWarehouseModel.updateStockBatch(updateProductWareouseList,corpid);
            } else {
                LOG.warn("no product warehouse update");
            }
//			if (superType && !productWarehouseStockMap.isEmpty()){
//				//没有空，表示productWarehouse有缺失
//			}
            //sku
            List<UpdateDataEntity> updateList = new ArrayList<>();
            for (PaasFormDataEntityExt entityExt : productEntityExtList){
                Double stock = entityExt.getData().getDouble(ProductEnum.STOCK.getAttr());
                if (Objects.equals(stock, skuStockMap.get(entityExt.getId()))) {
                    continue;
                }
                JSONObject json = new JSONObject();
                json.put(ProductEnum.STOCK.getAttr(),skuStockMap.getOrDefault(entityExt.getId(),0D));
                updateList.add(ExplainUtil.getUpdateData(entityExt.getId(),json,corpid));
            }
            if (!updateList.isEmpty()){
                productModel.updateBatch(updateList,corpid);
            } else {
                LOG.warn("no product update");
            }
        }
        LOG.warn("fixAllStock over");
        return "can u speak php";
    }

    /**
     * 去掉新建进流程的数据
     * @param idList
     * @param corpid
     */
    private void removeAddData(List<Long> idList, String corpid) {
        if (CollectionsUtil.isNotEmpty(idList)) {
            if (!commonHelp.isOpenWorkFlow(corpid)) {
                // 检测是否开通了工作流
                return;
            }
            // 查询审批中的任务
            Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            filterMap.put(StringConstant.CORPID, corpid);
            filterMap.put("dataIdIn", idList);
            filterMap.put("del", 0);
            filterMap.put("flowStatusIn", FlowStatusEnum.inApproval());
            filterMap.put("columns", " id, data_id, flow_status");
            List<WorkflowTaskEntity> taskList = workflowTaskModel.findEntities(filterMap);
            if (CollectionsUtil.isNotEmpty(taskList)) {
                List<Long> taskIdList = new ArrayList<>();
                taskList.forEach(item->{
                    taskIdList.add(item.getId());
                });
                filterMap.clear();
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("taskIdIn", taskIdList);
                filterMap.put("del", 0);
                List<WorkflowTransferDataEntity> list = workflowTransferDataModel.findEntities(filterMap);
                if (CollectionsUtil.isNotEmpty(list)) {
                    WorkflowTransferPOJO workflowTransferPOJO;
                    for (WorkflowTransferDataEntity item : list) {
                        workflowTransferPOJO = JSON.parseObject(item.getData().toJSONString(), WorkflowTransferPOJO.class);
                        Integer operate = workflowTransferPOJO.getOperate();
                        if (Objects.equals(WorkflowOperateEnum.ADD.getType(), operate)) {
//                            移除掉新建的入库单或者出库单
                            // 工作流的新建时，入库产品表和出库产品表都会生成；但是库存并未增加，所以需要移除掉新建进工作流的入库单和出库单
                            idList.remove(workflowTransferPOJO.getData().getId());
                        }
                    }
                }
            }
        }
    }

    /**
     * 修复某个公司(某个产品)的所有库存信息:sku、productWarehouse
     * 并且添加出入库单据
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixAllStockAddRecord", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixAllStockAddRecord(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (Objects.isNull(corpidList) || corpidList.size() != 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,"只允许刷一个公司");
        }
        if (Objects.isNull(fixDataJobDTO.getDataIdList())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,"dataIdList不需要也至少传个空数组");
        }
        LOG.warn("fixAllStock begin");
        String corpid = corpidList.get(0);
        PaasFormEntity instockForm = paasFormModel.getByBusinessType(XbbRefTypeEnum.OTHER_INSTOCK.getCode(),corpid);
        PaasFormEntity outstockForm = paasFormModel.getByBusinessType(XbbRefTypeEnum.OTHER_OUTSTOCK.getCode(),corpid);
        //0普通模式，不过滤出入库产品，不插入分仓数据；1高级模式，过滤出入库产品，插入未匹配到的分仓数据
        Long idGte = 0L;
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,corpid);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        List<WarehouseEntityExt> warehouseEntityExtList = warehouseModel.findEntitys(param);
        List<Long> warehouseIdList = new ArrayList<>();
        warehouseEntityExtList.forEach(item -> warehouseIdList.add(item.getId()));
        warehouseIdList.add(-1L);
        while (true) {
            param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            if (!fixDataJobDTO.getDataIdList().isEmpty()) {
                param.put("idIn",fixDataJobDTO.getDataIdList());
            }
            param.put("dataParentIdGte",0L);
            param.put("idGte",idGte);
            param.put("pageSize",1000);
            param.put("orderByStr","id asc");
            List<ProductEntityExt> productEntityExtList = productModel.findEntitys(param);
            if (productEntityExtList.isEmpty()) {
                if (idGte <= 0L){
                    LOG.warn(JSONObject.toJSONString(param));
                    return "When I put a question mark, it is not that I have a problem, but I think you have a problem.";
                }
                break;
            }
            LOG.warn("idGte:" + idGte);
            idGte = productEntityExtList.get(productEntityExtList.size()-1).getId();
            Map<Long,PaasFormDataEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> productIdList = new ArrayList<>();
            productEntityExtList.forEach(item -> {
                productIdList.add(item.getId());
                productMap.put(item.getId(), item);
            });
            //入库
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid",corpid);
            map.put("productIdIn",productIdList);
            map.put("warehouseIdIn",warehouseIdList);
            map.put("del",0);
            List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(map);
            List<Long> idList = new ArrayList<>();
            if (!instockProductEntityList.isEmpty()) {
                List<Long> instockIdList = new ArrayList<>();
                instockProductEntityList.forEach(item -> instockIdList.add(item.getIntoWarehouseId()));
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", instockIdList);
                filterMap.put("del", 0);
                idList = instockModel.findIds(filterMap);
            }
            Map<String,Double>  productWarehouseStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (InstockProductEntity entity : instockProductEntityList){
                if (!idList.contains(entity.getIntoWarehouseId())){
                    continue;
                }
                //productWarehouse
                String key = entity.getProductId() + "_" + entity.getWarehouseId();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                productWarehouseStock = Arith.add(productWarehouseStock,entity.getProductNum());
                productWarehouseStockMap.put(key,productWarehouseStock);
            }
            //出库
            List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(map);
            idList = new ArrayList<>();
            if (!outstockProductEntityList.isEmpty()) {
                List<Long> outstockIdList = new ArrayList<>();
                outstockProductEntityList.forEach(item -> outstockIdList.add(item.getOutWarehouseId()));
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", outstockIdList);
                filterMap.put("del", 0);
                idList = outstockModel.findIds(filterMap);
            }
            for (OutstockProductEntity entity : outstockProductEntityList){
                if (!idList.contains(entity.getOutWarehouseId())){
                    continue;
                }
                //productWarehouse
                String key = entity.getProductId() + "_" + entity.getWarehouseId();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                productWarehouseStock = Arith.sub(productWarehouseStock,entity.getProductNum());
                productWarehouseStockMap.put(key,productWarehouseStock);
            }
            param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            param.put("productIdIn",productIdList);
            List<WarehouseOristockEntity> warehouseOristockEntityList = warehouseOristockModel.findEntitys(param);
            List<Long> oriWarehouseIdList = new ArrayList<>();
            Map<Long,Long> oriWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            warehouseOristockEntityList.forEach(item -> {
                oriWarehouseMap.put(item.getId().longValue(),item.getWarehouseId());
                oriWarehouseIdList.add(item.getWarehouseId());
            });
            param.put("oriStockIdIn",oriWarehouseMap.keySet());
            param.put("productIdIn",productIdList);
            List<WarehouseOristockProductEntity> warehouseOristockProductEntityList = warehouseOristockProductModel.findEntitys(param);
            for (WarehouseOristockProductEntity warehouseOristockProductEntity : warehouseOristockProductEntityList) {
                if (oriWarehouseMap.containsKey(warehouseOristockProductEntity.getOristockId().longValue())){
                    Long warehouseId = oriWarehouseMap.get(warehouseOristockProductEntity.getOristockId().longValue());
                    String key = warehouseOristockProductEntity.getProductId() + "_" + warehouseId;
                    Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                    productWarehouseStock = Arith.add(productWarehouseStock,warehouseOristockProductEntity.getOristockNum());
                    productWarehouseStockMap.put(key,productWarehouseStock);
                }
            }
            //分仓
            param.clear();
            param.put("corpid",corpid);
            param.put("productIdIn",productIdList);
            param.put("warehouseChecked",1);
            param.put("del",0);
//            param.put("columns","corpid,id,product_id,warehouse_id,cost,ori_num");
            List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(param,1);
//            List<ProductWarehouseEntity> updateProductWareouseList = new ArrayList<>();
            Iterator<ProductWarehouseEntity> iterator = productWarehouseEntityList.iterator();
            //由于可能有老期初，同时又有全仓记录，先循环分仓记录，兼容老期初，再更新全仓记录
            List<InstockEntityExt> addInstockList = new ArrayList<>();
            List<OutstockEntityExt> addOutstockList = new ArrayList<>();
            while (iterator.hasNext()) {
                ProductWarehouseEntity entity = iterator.next();
                if (!Objects.equals(entity.getWarehouseId(),0L)){
                    String key = entity.getProductId() + "_" + entity.getWarehouseId();
                    if (entity.getOriNum() > 0 && !oriWarehouseIdList.contains(entity.getWarehouseId())) {
                        //老期初
                        Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                        productWarehouseStock = Arith.add(productWarehouseStock,entity.getOriNum());
                        productWarehouseStockMap.put(key,productWarehouseStock);
                    }
                    PaasFormDataEntity productEntityExt = productMap.get(entity.getProductId());
                    if (productWarehouseStockMap.containsKey(key)){
                        Double stock = productWarehouseStockMap.get(key);
                        if (!Objects.equals(entity.getNum(), stock)) {
                            if (entity.getNum() < stock) {
                                Double productNum = Arith.sub(stock,entity.getNum());
                                OutstockEntityExt outstockEntityExt = new OutstockEntityExt();
                                outstockEntityExt.setSerialNo(productEntityExt.getSerialNo() + " 系统生成出库单" + (addOutstockList.size()+1));
                                outstockEntityExt.setCorpid(corpid);
                                outstockEntityExt.setOwnerId("");
                                outstockEntityExt.setDepartmentId(0L);
                                outstockEntityExt.setAppId(outstockForm.getAppId());
                                outstockEntityExt.setMenuId(outstockForm.getMenuId());
                                outstockEntityExt.setFormId(outstockForm.getId());
                                outstockEntityExt.setFlowStatus(0);
                                outstockEntityExt.setCreatorId("");
                                outstockEntityExt.setAddTime(DateTimeUtil.getInt());
                                outstockEntityExt.setUpdateTime(DateTimeUtil.getInt());
                                JSONObject data = new JSONObject();
                                data.put(OutstockEnum.TYPE.getAttr(), String.valueOf(OutstockTypeEnum.OTHER_OUTSTOCK.getCode()));
                                data.put(OutstockEnum.WAREHOUSE_ID.getAttr(), entity.getWarehouseId());
                                data.put(OutstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), entity.getWarehouseName());
                                data.put(OutstockEnum.PRODUCT.getAttr(),Collections.singletonList(entity.getProductId()));
                                data.put(OutstockEnum.TIME.getAttr(),DateTimeUtil.getTodayInt());
                                OutstockProductEntity outstockProductEntity = new OutstockProductEntity();
                                outstockProductEntity.setCorpid(corpid);
                                outstockProductEntity.setParentId(entity.getParentId());
                                outstockProductEntity.setProductId(entity.getProductId());
                                outstockProductEntity.setWarehouseId(entity.getWarehouseId());
                                outstockProductEntity.setWarehouseName(entity.getWarehouseName());
                                outstockProductEntity.setProductNo(productEntityExt.getSerialNo());
                                outstockProductEntity.setProductSpecification(productEntityExt.getData().getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                                outstockProductEntity.setProductName(productEntityExt.getData().getString(ProductEnum.NAME.getAttr()));
                                outstockProductEntity.setProductNum(productNum);
                                outstockProductEntity.setProductUnit(productEntityExt.getData().getString(ProductEnum.UNIT.getAttr()));
                                outstockProductEntity.setProductPrice(productEntityExt.getData().getDouble(ProductEnum.PRICE.getAttr()));
                                outstockProductEntity.setCost(entity.getCost());
                                outstockProductEntity.setBatch("");
                                outstockProductEntity.setProduceDate(0L);
                                outstockProductEntity.setGuaranteePeriod(0L);
                                outstockProductEntity.setType(OutstockTypeEnum.OTHER_OUTSTOCK.getCode());
                                outstockProductEntity.setSort(1);
                                outstockProductEntity.setFormId(outstockForm.getId());
                                data.put("product",outstockProductEntity);
                                outstockEntityExt.setData(data);
                                addOutstockList.add(outstockEntityExt);
                            } else {
                                Double productNum = Arith.sub(entity.getNum(),stock);
                                InstockEntityExt instockEntityExt = new InstockEntityExt();
                                instockEntityExt.setSerialNo(productEntityExt.getSerialNo() + " 系统生成入库单:" + (addInstockList.size()+1));
                                instockEntityExt.setCorpid(corpid);
                                instockEntityExt.setOwnerId("");
                                instockEntityExt.setDepartmentId(0L);
                                instockEntityExt.setAppId(instockForm.getAppId());
                                instockEntityExt.setMenuId(instockForm.getMenuId());
                                instockEntityExt.setFormId(instockForm.getId());
                                instockEntityExt.setFlowStatus(0);
                                instockEntityExt.setCreatorId("");
                                instockEntityExt.setAddTime(DateTimeUtil.getInt());
                                instockEntityExt.setUpdateTime(DateTimeUtil.getInt());
                                JSONObject data = new JSONObject();
                                data.put(InstockEnum.TYPE.getAttr(), String.valueOf(InstockTypeEnum.OTHER_INSTOCK.getCode()));
                                data.put(InstockEnum.WAREHOUSE_ID.getAttr(), entity.getWarehouseId());
                                data.put(InstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), entity.getWarehouseName());
                                data.put(InstockEnum.PRODUCT.getAttr(),Collections.singletonList(entity.getProductId()));
                                data.put(InstockEnum.TIME.getAttr(),DateTimeUtil.getTodayInt());
                                InstockProductEntity instockProductEntity = new InstockProductEntity();
                                instockProductEntity.setCorpid(corpid);
                                instockProductEntity.setParentId(entity.getParentId());
                                instockProductEntity.setProductId(entity.getProductId());
                                instockProductEntity.setWarehouseId(entity.getWarehouseId());
                                instockProductEntity.setWarehouseName(entity.getWarehouseName());
                                instockProductEntity.setProductNo(productEntityExt.getSerialNo());
                                instockProductEntity.setProductSpecification(productEntityExt.getData().getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                                instockProductEntity.setProductName(productEntityExt.getData().getString(ProductEnum.NAME.getAttr()));
                                instockProductEntity.setProductNum(productNum);
                                instockProductEntity.setProductUnit(productEntityExt.getData().getString(ProductEnum.UNIT.getAttr()));
                                instockProductEntity.setProductPrice(productEntityExt.getData().getDouble(ProductEnum.PRICE.getAttr()));
                                instockProductEntity.setCost(entity.getCost());
                                instockProductEntity.setBatch("");
                                instockProductEntity.setProduceDate(0L);
                                instockProductEntity.setGuaranteePeriod(0L);
                                instockProductEntity.setSort(1);
                                instockProductEntity.setType(InstockTypeEnum.OTHER_INSTOCK.getCode());
                                instockProductEntity.setFormId(instockForm.getId());
                                data.put("product",instockProductEntity);
                                instockEntityExt.setData(data);
                                addInstockList.add(instockEntityExt);
                            }
                            entity.setNum(stock);
                            productWarehouseStockMap.remove(key);
                        }
                    }else {
                        Double productNum = entity.getNum();
                        if (productNum <= 0) {
                            continue;
                        }
                        InstockEntityExt instockEntityExt = new InstockEntityExt();
                        instockEntityExt.setSerialNo(productEntityExt.getSerialNo() + " 系统生成入库单:" + (addInstockList.size()+1));
                        instockEntityExt.setCorpid(corpid);
                        instockEntityExt.setOwnerId("");
                        instockEntityExt.setDepartmentId(0L);
                        instockEntityExt.setAppId(instockForm.getAppId());
                        instockEntityExt.setMenuId(instockForm.getMenuId());
                        instockEntityExt.setFormId(instockForm.getId());
                        instockEntityExt.setFlowStatus(0);
                        instockEntityExt.setCreatorId("");
                        instockEntityExt.setAddTime(DateTimeUtil.getInt());
                        instockEntityExt.setUpdateTime(DateTimeUtil.getInt());
                        JSONObject data = new JSONObject();
                        data.put(InstockEnum.TYPE.getAttr(), String.valueOf(InstockTypeEnum.OTHER_INSTOCK.getCode()));
                        data.put(InstockEnum.WAREHOUSE_ID.getAttr(), entity.getWarehouseId());
                        data.put(InstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), entity.getWarehouseName());
                        data.put(InstockEnum.PRODUCT.getAttr(),Collections.singletonList(entity.getProductId()));
                        data.put(InstockEnum.TIME.getAttr(),DateTimeUtil.getTodayInt());
                        InstockProductEntity instockProductEntity = new InstockProductEntity();
                        instockProductEntity.setCorpid(corpid);
                        instockProductEntity.setParentId(entity.getParentId());
                        instockProductEntity.setProductId(entity.getProductId());
                        instockProductEntity.setWarehouseId(entity.getWarehouseId());
                        instockProductEntity.setWarehouseName(entity.getWarehouseName());
                        instockProductEntity.setProductNo(productEntityExt.getSerialNo());
                        instockProductEntity.setProductSpecification(productEntityExt.getData().getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                        instockProductEntity.setProductName(productEntityExt.getData().getString(ProductEnum.NAME.getAttr()));
                        instockProductEntity.setProductNum(productNum);
                        instockProductEntity.setProductUnit(productEntityExt.getData().getString(ProductEnum.UNIT.getAttr()));
                        instockProductEntity.setProductPrice(productEntityExt.getData().getDouble(ProductEnum.PRICE.getAttr()));
                        instockProductEntity.setCost(entity.getCost());
                        instockProductEntity.setBatch("");
                        instockProductEntity.setProduceDate(0L);
                        instockProductEntity.setGuaranteePeriod(0L);
                        instockProductEntity.setSort(1);
                        instockProductEntity.setType(InstockTypeEnum.OTHER_INSTOCK.getCode());
                        instockProductEntity.setFormId(instockForm.getId());
                        data.put("product",instockProductEntity);
                        instockEntityExt.setData(data);
                        addInstockList.add(instockEntityExt);
                    }
//                    updateProductWareouseList.add(entity);
                    iterator.remove();
                }
            }
            //全仓记录
            if (!addInstockList.isEmpty()) {
                for (InstockEntityExt instockEntityExt : addInstockList) {
                    Object productObj = instockEntityExt.getData().remove("product");
                    instockModel.insert(instockEntityExt);
                    InstockProductEntity instockProductEntity = JSONObject.parseObject(JSONObject.toJSONString(productObj),InstockProductEntity.class);
                    instockProductEntity.setIntoWarehouseId(instockEntityExt.getId());
                    instockProductModel.insert(instockProductEntity);
                }

            }
            if (!addOutstockList.isEmpty()) {
                for (OutstockEntityExt outstockEntityExt : addOutstockList) {
                    Object productObj = outstockEntityExt.getData().remove("product");
                    outstockModel.insert(outstockEntityExt);
                    OutstockProductEntity outstockProductEntity = JSONObject.parseObject(JSONObject.toJSONString(productObj),OutstockProductEntity.class);
                    outstockProductEntity.setOutWarehouseId(outstockEntityExt.getId());
                    outstockProductModel.insert(outstockProductEntity);
                }
            }
        }
        LOG.warn("fixAllStock over");
        return "can u speak php";
    }

    @RequestMapping(value = "/fixAllBatchStock", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixAllBatchStock(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (Objects.isNull(corpidList) || corpidList.size() != 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,"只允许刷一个公司");
        }
        LOG.warn("fixAllBatchStock begin");
        String corpid = corpidList.get(0);
        //0普通模式，不过滤出入库产品，不插入分仓数据；1高级模式，过滤出入库产品，插入未匹配到的分仓数据
        Boolean superType = Objects.equals(fixDataJobDTO.getType(),1);
        Long dataDataMark = 0L;
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
        paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
        while (!paasFormDataEntityExtList.isEmpty()) {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            if (Objects.nonNull(fixDataJobDTO.getDataIdList()) && !fixDataJobDTO.getDataIdList().isEmpty()) {
                boolQueryBuilder.filter(termsQuery("dataId", fixDataJobDTO.getDataIdList()));
            }
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.mustNot(termQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.PARENT_ID),0));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 1000, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_PRODUCT, dataDataMark);
            paasFormDataEntityExtList = listVO.getList();
            dataDataMark = listVO.getDataIdMark();
            if (paasFormDataEntityExtList.isEmpty()) {
//                if (dataDataMark <= 0L){
//                    return "When I hit the question mark, it wasn't me that asked the question, but I thought you had the question.";
//                }
                continue;
            }
            Map<Long,PaasFormDataEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> productIdList = new ArrayList<>();
            paasFormDataEntityExtList.forEach(item -> {
                productIdList.add(item.getDataId());
                if (superType) {
                    productMap.put(item.getDataId(), item);
                }
            });
            //入库
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid",corpid);
            map.put("productIdIn",productIdList);
            map.put("del",0);
            List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(map);
            List<Long> idList = new ArrayList<>();
            if (!instockProductEntityList.isEmpty()) {
                List<Long> instockIdList = new ArrayList<>();
                instockProductEntityList.forEach(item -> instockIdList.add(item.getIntoWarehouseId()));
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", instockIdList);
                filterMap.put("del", 0);
                idList = instockModel.findIds(filterMap);
            }
            removeAddData(idList,corpid);
            Map<String,Double>  productWarehouseStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (InstockProductEntity entity : instockProductEntityList){
                if (!idList.contains(entity.getIntoWarehouseId())){
                    continue;
                }
                //batch
                String key = entity.getProductId() + "_" + entity.getWarehouseId() + "_" + entity.getBatch() + "_" + entity.getProduceDate() + "_" + entity.getGuaranteePeriod();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                productWarehouseStock = Arith.add(productWarehouseStock,entity.getProductNum());
                productWarehouseStockMap.put(key,productWarehouseStock);
            }
            //出库
            List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(map);
            idList = new ArrayList<>();
            if (!outstockProductEntityList.isEmpty()) {
                List<Long> outstockIdList = new ArrayList<>();
                outstockProductEntityList.forEach(item -> outstockIdList.add(item.getOutWarehouseId()));
                Map<String, Object> filterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                filterMap.put(StringConstant.CORPID, corpid);
                filterMap.put("idIn", outstockIdList);
                filterMap.put("del", 0);
                idList = outstockModel.findIds(filterMap);
            }
            removeAddData(idList,corpid);
            for (OutstockProductEntity entity : outstockProductEntityList){
                if (!idList.contains(entity.getOutWarehouseId())){
                    continue;
                }
                //batch
                String key = entity.getProductId() + "_" + entity.getWarehouseId() + "_" + entity.getBatch() + "_" + entity.getProduceDate() + "_" + entity.getGuaranteePeriod();
                Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                productWarehouseStock = Arith.sub(productWarehouseStock,entity.getProductNum());
                productWarehouseStockMap.put(key,productWarehouseStock);
            }
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            param.put("productIdIn",productIdList);
            List<WarehouseOristockEntity> warehouseOristockEntityList = warehouseOristockModel.findEntitys(param);
            Map<Long,Long> oriWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            warehouseOristockEntityList.forEach(item -> oriWarehouseMap.put(item.getId().longValue(),item.getWarehouseId()));
            param.put("oriStockIdIn",oriWarehouseMap.keySet());
            param.put("productIdIn",productIdList);
            List<WarehouseOristockProductEntity> warehouseOristockProductEntityList = warehouseOristockProductModel.findEntitys(param);
            for (WarehouseOristockProductEntity warehouseOristockProductEntity : warehouseOristockProductEntityList) {
                if (oriWarehouseMap.containsKey(warehouseOristockProductEntity.getOristockId().longValue())){
                    Long warehouseId = oriWarehouseMap.get(warehouseOristockProductEntity.getOristockId().longValue());
                    String key = warehouseOristockProductEntity.getProductId() + "_" + warehouseId + "_" + warehouseOristockProductEntity.getBatch() + "_" + warehouseOristockProductEntity.getProduceDate() + "_" + warehouseOristockProductEntity.getGuaranteePeriod();
                    Double productWarehouseStock = productWarehouseStockMap.getOrDefault(key,0D);
                    productWarehouseStock = Arith.add(productWarehouseStock,warehouseOristockProductEntity.getOristockNum());
                    productWarehouseStockMap.put(key,productWarehouseStock);
                }
            }
            //分仓
            boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_CHECKED),1));
            boolQueryBuilder.filter(termsQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCT_ID),productIdList));
            List<PaasFormDataEntity> productStockEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO,boolQueryBuilder,PaasFormDataEntity.class, Arrays.asList("corpid","id", ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.PRODUCT_ID), ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.WAREHOUSE_ID), ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.BATCH), ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.PRODUCE_DATE), ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.GUARANTEE_PERIOD)));
            List<ProductStockEntity> productStockEntities = transferSubFormHelper.transferFormDataToProductStockList(productStockEntityList);

            List<ProductStockEntity> updateProductStockList = new ArrayList<>();
            for (ProductStockEntity entity : productStockEntities){
                String key = entity.getProductId() + "_" + entity.getWarehouseId() + "_" + entity.getBatch() + "_" + entity.getProduceDate() + "_" + entity.getGuaranteePeriod();
                if (productWarehouseStockMap.containsKey(key)){
                    entity.setNum(productWarehouseStockMap.get(key));
                    productWarehouseStockMap.remove(key);
                }else {
                    entity.setNum(0D);
                }
                updateProductStockList.add(entity);
            }
            if (!updateProductStockList.isEmpty()){
                productStockModel.updateStockBatch(updateProductStockList,corpid);
            }
        }
        LOG.warn("fixAllBatchStock over");
        return null;
    }

    /**
     *  修复产品编号数据
     *
     * @param productDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixProductNo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixProductNo(@RequestBody @Valid ProductDTO productDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(productDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = productDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = productModel.getCorpidList();
        }
        int corpidCount = 0;
        Long parentId;
        for (String corpid : corpidList) {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.mustNot(termQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), 0));
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_PRODUCT.getType()));
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.query(boolQueryBuilder);
            sourceBuilder.sort(StringConstant.SAAS_LINK_BUSINESS_ID);
            SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PRODUCT.getIndex());
            searchRequest.source(sourceBuilder);
            long totalCountLong = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
            int totalCount = (int) totalCountLong;
            LOG.warn("corpid:" + corpid + "es中共有子产品" + totalCount + "条数据");
            int pageSize = 1000;
            int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
            for (int page = 0; page < totalPage; page++) {
                //设置分页
                PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
                XbbAggregatedPage<PaasFormDataEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntity.class);
                if (esEntities == null) {
                    LOG.warn("corpid:" + corpid + "查询es服务器没有查到任何数据");
                }
                List<PaasFormDataEntity> productEntityExtList = esEntities.getContent();
                if (productEntityExtList.isEmpty()) {
                    continue;
                }
                Set<Long> parentIdIn = new HashSet<>(productEntityExtList.size());
                for (PaasFormDataEntity productEntityExt : productEntityExtList) {
                    if (Objects.nonNull(productEntityExt.getData())) {
                        parentId = productEntityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr());
                        if (Objects.nonNull(parentId) && !Objects.equals(parentId, 0L)) {
                            parentIdIn.add(parentId);
                        }
                    }
                }
                if (parentIdIn.isEmpty()) {
                    continue;
                }
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), parentIdIn));
                boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                List<PaasFormDataEntityExt> list = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(FieldTypeEnum.SERIALNO.getAlias(), FieldTypeEnum.DATAID.getAlias(), ProductEnum.getAttrConnectData(ProductEnum.PRODUCT_NO)));
                Map<Long, String> parentSerialNoMap = new HashMap<>(list.size());
                for (PaasFormDataEntityExt paasFormDataEntityExt : list) {
                    parentSerialNoMap.put(paasFormDataEntityExt.getDataId(), paasFormDataEntityExt.getSerialNo());
                }
                List<UpdateDataEntity> updateDataEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                productEntityExtList.forEach(item -> {
                    UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                    updateDataEntity.setCorpid(item.getCorpid());
                    updateDataEntity.setId(item.getId());
                    updateDataEntity.setSerialNo(parentSerialNoMap.getOrDefault(item.getData().getLong(ProductEnum.PARENT_ID.getAttr()), ""));
                    updateDataEntityList.add(updateDataEntity);
                });
                if (CollectionsUtil.isNotEmpty(updateDataEntityList)) {
                    productModel.updateBatchSerialNo(updateDataEntityList);
                }
            }
            ++corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("time:" + (DateTimeUtil.getInt() - start));
        LOG.warn("----------------fix ProductNo over----------");
        return null;
    }

    @RequestMapping(value = "/addChildIds", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String addChildIds(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = productModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(ParameterConstant.CORPID, corpid);
            param.put("pageSize", 1000);
            param.put("childIdsIsNull", 1);
            param.put("parentId", 0);
            param.put("orderByStr", "id");
            param.put("addTimeEnd", fixDataJobDTO.getAddTime());
            boolean addFlag = true;
            while (addFlag) {
                List<ProductUserEntity> productUserEntityList = productUserModel.findEntitys(param);
                if (Objects.isNull(productUserEntityList) || productUserEntityList.isEmpty()) {
                    addFlag = false;
                } else {
                    LOG.warn("遍历id到" + productUserEntityList.get(productUserEntityList.size() - 1).getId());
                    param.put("idGte", productUserEntityList.get(productUserEntityList.size() - 1).getId());
                    List<Long> parentIdIn = new ArrayList<>();
                    for (ProductUserEntity productUserEntity : productUserEntityList) {
                        if (Objects.nonNull(productUserEntity.getDataId())) {
                            parentIdIn.add(productUserEntity.getDataId());
                        }
                    }
                    if (parentIdIn.isEmpty()) {
                        continue;
                    }
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                    boolQueryBuilder.filter(termsQuery("data." + ProductEnum.PARENT_ID.getAttr(), parentIdIn));
                    List<String> fieldList = new ArrayList<>();
                    fieldList.add(StringConstant.SAAS_LINK_BUSINESS_ID);
                    fieldList.add("data." + ProductEnum.PARENT_ID.getAttr());
                    List<PaasFormDataEntity> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntity.class, fieldList);
                    Map<Long, List<Long>> childProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    childProductList.forEach(child -> {
                        Long parentId = null;
                        if (Objects.nonNull(child.getData()) && Objects.nonNull(child.getData().getLong(ProductEnum.PARENT_ID.getAttr()))) {
                            parentId = child.getData().getLong(ProductEnum.PARENT_ID.getAttr());
                        }
                        if (Objects.nonNull(parentId)) {
                            List<Long> childIdList = childProductMap.getOrDefault(parentId, new ArrayList<>());
                            childIdList.add(child.getId());
                            childProductMap.put(parentId, childIdList);
                        }
                    });
                    for (ProductUserEntity productUserEntity : productUserEntityList) {
                        List<Long> childProductIdList = childProductMap.get(productUserEntity.getDataId());
                        if (CollectionsUtil.isNotEmpty(childProductIdList)) {
                            productUserEntity.setChildIds(JSON.toJSONString(childProductIdList));
                        }
                        productUserEntity.setFlag(1);
                    }
                    if (!productUserEntityList.isEmpty()) {
                        productUserDao.updateBatchChildIds(productUserEntityList, corpid);
                    }
                }
            }
            ++corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/productAssociationUser", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String productAssociationUser(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = productModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("pageSize", 1000);
            param.put("parentId", 0);
            param.put("orderByStr", "id");
            param.put("childIdsNotNull", 1);
            param.put("flag", 1);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(ParameterConstant.CORPID, corpid);
            List<ProductUserEntity> childProductUserList = new ArrayList<>();
            boolean addFlag = true;
            while (addFlag) {
                List<ProductUserEntity> productUserEntityList = productUserModel.findEntitys(param);
                if (Objects.isNull(productUserEntityList) || productUserEntityList.isEmpty()) {
                    addFlag = false;
                } else {
                    LOG.warn("遍历id到" + productUserEntityList.get(productUserEntityList.size() - 1).getId());
                    param.put("idGte", productUserEntityList.get(productUserEntityList.size() - 1).getId());
                    ProductUserEntity userEntity;
                    for (ProductUserEntity productUserEntity : productUserEntityList) {
                        if (Objects.nonNull(productUserEntity.getChildIds())) {
                            List<Long> childProductIdList = JSON.parseArray(productUserEntity.getChildIds()).toJavaList(Long.class);
                            if (CollectionsUtil.isNotEmpty(childProductIdList)) {
                                for (Long childId : childProductIdList) {
                                    userEntity = new ProductUserEntity();
                                    userEntity.setParentId(productUserEntity.getDataId());
                                    userEntity.setCorpid(productUserEntity.getCorpid());
                                    userEntity.setUserName(productUserEntity.getUserName());
                                    userEntity.setUserAvatar(productUserEntity.getUserAvatar());
                                    userEntity.setRelationId(productUserEntity.getRelationId());
                                    userEntity.setType(productUserEntity.getType());
                                    userEntity.setDataId(childId);
                                    childProductUserList.add(userEntity);
                                }
                            }
                        }
                    }
                }
            }
            if (CollectionsUtil.isNotEmpty(childProductUserList))  {
                int insertTotal = childProductUserList.size();
                int insertPageSize = 1000;
                int insertTotalPage = (insertTotal % insertPageSize == 0) ? (insertTotal / insertPageSize) : (insertTotal / insertPageSize) + 1;
                for (int page = 0; page < insertTotalPage; page++) {
                    List<ProductUserEntity> insertList;
                    if (page == insertTotalPage - 1) {
                        insertList = childProductUserList.subList(insertPageSize * page, childProductUserList.size());
                    } else {
                        insertList = childProductUserList.subList(insertPageSize * page, insertPageSize * (page + 1));
                    }
                    productUserModel.inserBatch(insertList);
                }
            }
            ++corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/fixErrorProductAssociationUser", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixErrorProductAssociationUser(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = productModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("pageSize", 1000);
            param.put("parentId", 0);
            param.put("orderByStr", "id");
            param.put("childIdsNotNull", 1);
            param.put("flagIsNull", 1);
            param.put("addTimeEnd", fixDataJobDTO.getAddTime());
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(ParameterConstant.CORPID, corpid);
            List<ProductUserEntity> childProductUserList = new ArrayList<>();
            boolean addFlag = true;
            Map<String, Object> childParam;
            while (addFlag) {
                List<ProductUserEntity> productUserEntityList = productUserModel.findEntitys(param);
                if (Objects.isNull(productUserEntityList) || productUserEntityList.isEmpty()) {
                    addFlag = false;
                } else {
                    LOG.warn("遍历id到" + productUserEntityList.get(productUserEntityList.size() - 1).getId());
                    param.put("idGte", productUserEntityList.get(productUserEntityList.size() - 1).getId());
                    Set<ProductUserComparePojo> parentSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Set<Long> parentIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Set<Long> dataIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Set<String> relationIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    ProductUserComparePojo productUserComparePojo;
                    for (ProductUserEntity productUserEntity : productUserEntityList) {
                        parentIdIn.add(productUserEntity.getDataId());
                        relationIdIn.add(productUserEntity.getRelationId());
                        List<Long> childProductIdList = JSON.parseArray(productUserEntity.getChildIds()).toJavaList(Long.class);
                        for (Long childId : childProductIdList) {
                            productUserComparePojo = new ProductUserComparePojo(productUserEntity.getDataId(), childId, productUserEntity.getType(), productUserEntity.getRelationId());
                            parentSet.add(productUserComparePojo);
                            dataIdIn.add(childId);
                        }
                    }
                    childParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    childParam.put("dataIdIn", dataIdIn);
                    childParam.put("parentIdIn", parentIdIn);
                    childParam.put("relationIdIn", relationIdIn);
                    childParam.put(ParameterConstant.CORPID, corpid);
                    childParam.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                    List<ProductUserEntity> childUserList = productUserModel.findEntitys(childParam);
                    Set<ProductUserComparePojo> childSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (ProductUserEntity productUserEntity : childUserList) {
                        childSet.add(new ProductUserComparePojo(productUserEntity.getParentId(), productUserEntity.getDataId(), productUserEntity.getType(), productUserEntity.getRelationId()));
                    }
                    parentSet.removeAll(childSet);
                    ProductUserEntity productUserEntity;
                    for (ProductUserComparePojo userComparePojo : parentSet) {
                        productUserEntity = new ProductUserEntity();
                        productUserEntity.setParentId(userComparePojo.getParentId());
                        productUserEntity.setDataId(userComparePojo.getDataId());
                        productUserEntity.setCorpid(corpid);
                        productUserEntity.setType(userComparePojo.getType());
                        productUserEntity.setRelationId(userComparePojo.getRelationId());
                        childProductUserList.add(productUserEntity);
                    }
                }
            }
            if (CollectionsUtil.isNotEmpty(childProductUserList))  {
                int insertTotal = childProductUserList.size();
                int insertPageSize = 1000;
                int insertTotalPage = (insertTotal % insertPageSize == 0) ? (insertTotal / insertPageSize) : (insertTotal / insertPageSize) + 1;
                for (int page = 0; page < insertTotalPage; page++) {
                    List<ProductUserEntity> insertList;
                    if (page == insertTotalPage - 1) {
                        insertList = childProductUserList.subList(insertPageSize * page, childProductUserList.size());
                    } else {
                        insertList = childProductUserList.subList(insertPageSize * page, insertPageSize * (page + 1));
                    }
                    productUserModel.inserBatch(insertList);
                }
            }
            ++corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/fixErrorProductUser", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixAllErrorProductAssociationUser(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = productModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("pageSize", 1000);
            param.put("parentId", 0);
            param.put("orderByStr", "id");
            param.put("addTimeEnd", fixDataJobDTO.getAddTime());
            param.put("addTimeStart", fixDataJobDTO.getAddTimeStart());
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(ParameterConstant.CORPID, corpid);
            List<ProductUserEntity> childProductUserList = new ArrayList<>();
            boolean addFlag = true;
            Map<String, Object> childParam;
            while (addFlag) {
                List<ProductUserEntity> productUserEntityList = productUserModel.findEntitys(param);
                if (Objects.isNull(productUserEntityList) || productUserEntityList.isEmpty()) {
                    addFlag = false;
                } else {
                    LOG.warn("遍历id到" + productUserEntityList.get(productUserEntityList.size() - 1).getId());
                    param.put("idGte", productUserEntityList.get(productUserEntityList.size() - 1).getId());
                    Set<ProductUserComparePojo> parentSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Set<Long> parentIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Set<Long> dataIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Set<String> relationIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    ProductUserComparePojo productUserComparePojo;
                    for (ProductUserEntity productUserEntity : productUserEntityList) {
                        relationIdIn.add(productUserEntity.getRelationId());
                        parentIdIn.add(productUserEntity.getDataId());
                    }
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                    boolQueryBuilder.filter(termsQuery("data." + ProductEnum.PARENT_ID.getAttr(), parentIdIn));
                    List<String> fieldList = new ArrayList<>();
                    fieldList.add(StringConstant.SAAS_LINK_BUSINESS_ID);
                    fieldList.add("data." + ProductEnum.PARENT_ID.getAttr());
                    List<PaasFormDataEntity> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntity.class, fieldList);
                    Map<Long, List<Long>> childProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    childProductList.forEach(child -> {
                        Long parentId = null;
                        if (Objects.nonNull(child.getData()) && Objects.nonNull(child.getData().getLong(ProductEnum.PARENT_ID.getAttr()))) {
                            parentId = child.getData().getLong(ProductEnum.PARENT_ID.getAttr());
                        }
                        if (Objects.nonNull(parentId)) {
                            List<Long> childIdList  = childProductMap.getOrDefault(parentId, new ArrayList<>());
                            childIdList.add(child.getId());
                            childProductMap.put(parentId, childIdList);
                        }
                    });
                    for (ProductUserEntity productUserEntity : productUserEntityList) {
                        List<Long> childProductIdList = childProductMap.get(productUserEntity.getDataId());
                        if (Objects.nonNull(childProductIdList)) {
                            for (Long childId : childProductIdList) {
                                productUserComparePojo = new ProductUserComparePojo(productUserEntity.getDataId(), childId, productUserEntity.getType(), productUserEntity.getRelationId());
                                parentSet.add(productUserComparePojo);
                                dataIdIn.add(childId);
                            }
                        }
                    }
                    childParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    childParam.put("dataIdIn", dataIdIn);
                    childParam.put("parentIdIn", parentIdIn);
                    childParam.put("relationIdIn", relationIdIn);
                    childParam.put(ParameterConstant.CORPID, corpid);
                    childParam.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                    List<ProductUserEntity> childUserList = productUserModel.findEntitys(childParam);
                    Set<ProductUserComparePojo> childSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (ProductUserEntity productUserEntity : childUserList) {
                        childSet.add(new ProductUserComparePojo(productUserEntity.getParentId(), productUserEntity.getDataId(), productUserEntity.getType(), productUserEntity.getRelationId()));
                    }
                    parentSet.removeAll(childSet);
                    ProductUserEntity productUserEntity;
                    for (ProductUserComparePojo userComparePojo : parentSet) {
                        productUserEntity = new ProductUserEntity();
                        productUserEntity.setParentId(userComparePojo.getParentId());
                        productUserEntity.setDataId(userComparePojo.getDataId());
                        productUserEntity.setCorpid(corpid);
                        productUserEntity.setType(userComparePojo.getType());
                        productUserEntity.setRelationId(userComparePojo.getRelationId());
                        childProductUserList.add(productUserEntity);
                    }
                }
            }
            if (CollectionsUtil.isNotEmpty(childProductUserList))  {
                int insertTotal = childProductUserList.size();
                int insertPageSize = 1000;
                int insertTotalPage = (insertTotal % insertPageSize == 0) ? (insertTotal / insertPageSize) : (insertTotal / insertPageSize) + 1;
                for (int page = 0; page < insertTotalPage; page++) {
                    List<ProductUserEntity> insertList;
                    if (page == insertTotalPage - 1) {
                        insertList = childProductUserList.subList(insertPageSize * page, childProductUserList.size());
                    } else {
                        insertList = childProductUserList.subList(insertPageSize * page, insertPageSize * (page + 1));
                    }
                    productUserModel.inserBatch(insertList);
                }
            }
            ++corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("操作成功");
        return null;
    }

//    @RequestMapping(value = "/fixProductWarehouse", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixProductWarehouse(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = productModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
            List<PaasFormDataEntity> warehouseList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_WAREHOUSE, boolQueryBuilder, PaasFormDataEntity.class, fieldList);
            int totalCount = warehouseList.size();
            LOG.warn("该公司" + corpid +"在es中共有" + totalCount + "条仓库数据");
            List<Long> warehouseIdList = new ArrayList<>();
            warehouseIdList.add(0L);
            warehouseList.forEach(item -> {
                warehouseIdList.add(item.getDataId());
            });

            boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_CHECKED), 1));
            boolQueryBuilder.mustNot(termsQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_ID) , warehouseIdList));
            List<PaasFormDataEntity> productWarehouseList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE, boolQueryBuilder, PaasFormDataEntity.class, null);

            //List<ProductWarehouseEntity> productWarehouseList = productWarehouseModel.findEntitys(param);
            if (!productWarehouseList.isEmpty()) {
                List<ProductWarehouseEntity> productWarehouseEntities = transferSubFormHelper.transferFormDataToProductWarehouseList(productWarehouseList);
                //List<Long> idInList = new ArrayList<>(productWarehouseList.size());
                //productWarehouseList.forEach(item -> idInList.add(item.getId()));
                productWarehouseModel.deleteBatch(corpid, productWarehouseEntities);
                LOG.warn("删除了" + productWarehouseEntities.size() + "条异常product_warehouse数据");
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(ParameterConstant.CORPID, corpid);
            param.put("warehouseChecked", 1);
            param.put("warehouseId", 0L);
            List<ProductWarehouseEntity> allProductWarehouseList = productWarehouseModel.findEntitysWithWarehouseChecked(param,1);
            if (!allProductWarehouseList.isEmpty()) {
                List<Long> productIdInList = new ArrayList<>(allProductWarehouseList.size());
                allProductWarehouseList.forEach(item -> productIdInList.add(item.getProductId()));
                param.remove("warehouseId");
                param.put("productIdIn", productIdInList);
                List<ProductWarehouseEntity> departProductWarehouseList = productWarehouseModel.findEntitysWithWarehouseChecked(param,1);
                Map<Long, Double> allNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                departProductWarehouseList.forEach(item -> {
                    if (!Objects.equals(item.getWarehouseId(), 0L)) {
                        if (allNumMap.containsKey(item.getProductId())) {
                            allNumMap.put(item.getProductId(), Arith.add(item.getNum(), allNumMap.get(item.getProductId())));
                        } else {
                            allNumMap.put(item.getProductId(), item.getNum());
                        }
                    }
                });
                List<ProductWarehouseEntity> updateList = new ArrayList<>();
                allProductWarehouseList.forEach(item -> {
                    if (allNumMap.containsKey(item.getProductId()) && !Objects.equals(item.getNum(), allNumMap.get(item.getProductId()))) {
                        item.setNum(allNumMap.get(item.getProductId()));
                        updateList.add(item);
                    }
                });
                if (!updateList.isEmpty()) {
                    productWarehouseModel.updateStockBatch(updateList, corpid);
                }
                LOG.warn("更新了" + updateList.size() + "条异常product_warehouse全仓数据");
            }
            ++ corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/fixSaleOpportunityExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixSaleOpportunityExplain(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = companyModel.getCorpidList();
        int index = 1;
        for (String corpid : corpidList) {
            LOG.warn("fixSaleOpportunityExplain:" + index + "/" + corpidList.size());
            index++;
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("businessType",XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
            List<PaasFormExplainEntity> paasFormExplainEntityList = paasFormExplainModel.list(param);
            for (PaasFormExplainEntity entity : paasFormExplainEntityList) {
                boolean update = false;
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(entity.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(),SalesOpportunityEnum.ESTIMATE_AMOUNT.getAttr()) && Objects.equals(fieldAttrEntity.getEditable(), 0)) {
                        fieldAttrEntity.setEditable(1);
                        update = true;
                        break;
                    }
                }
                if (update) {
                    entity.setExplains(JSONArray.toJSONString(fieldAttrEntityList));
                    paasFormExplainModel.update(entity);
                }
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("fixSaleOpportunityExplain over");
        return null;
    }


//    @RequestMapping(value = "/fixSkuStock2", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixSkuStock(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList;
        if (Objects.isNull(fixDataJobDTO.getCorpidList()) || fixDataJobDTO.getCorpidList().isEmpty()){
            corpidList = productModel.getCorpidList();
        }else {
            corpidList = fixDataJobDTO.getCorpidList();
        }
        int index = 0;
//        int productNeedUpdateSize = 0;
//        int stockNeedUpdateSize = 0;
        for (String corpid : corpidList) {
            FormConfigEntity formConfigEntity = formConfigModel.getEntityByBusinessType(corpid, XbbRefTypeEnum.OUTSTOCK.getCode(), FormConfigEnum.OUTSTOCK_INSUFFICIENT_NOT_ALLOW_WAREHOUSING.getConfig());
            //有配置，且值为0，允许负库存
            boolean allowNeg = Objects.nonNull(formConfigEntity) && Objects.equals(formConfigEntity.getConfigValue(),"0");
            index++;
            LOG.warn("fixSkuStock:" + corpid + index + "/" + corpidList.size());
            Long idGte = 0L;
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put(StringConstant.CORPID,corpid);
            map.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            map.put("orderByStr","id");
            map.put("dataParentIdGte",0);
            map.put("pageSize",1000);
            while (true){
                map.put("idGte",idGte);
                List<ProductEntityExt> productEntityExtList = productModel.findEntitys(map);
                if (productEntityExtList.isEmpty()){
                    break;
                }
                idGte = productEntityExtList.get(productEntityExtList.size() - 1).getId();
                List<Long> idList = new ArrayList<>();
                productEntityExtList.forEach(item -> idList.add(item.getId()));
                Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID,corpid);
                param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
                param.put("productIdIn",idList);
                param.put("warehouseChecked",1);
                List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(param,1);
                Map<Long,Double> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                List<ProductWarehouseEntity> allWarehouoseList = new ArrayList<>();
                List<ProductWarehouseEntity> updateList = new ArrayList<>();
                for (ProductWarehouseEntity entity : productWarehouseEntityList) {
                    if (Objects.equals(entity.getWarehouseId(), 0L)) {
                        allWarehouoseList.add(entity);
                    }else {
                        Double stock = stockMap.getOrDefault(entity.getProductId(),0D);
                        Double amendNum = entity.getNum();
                        if (amendNum < 0D && !allowNeg){
                            amendNum = 0D;
                            entity.setNum(amendNum);
                            updateList.add(entity);
                        }
                        stock = Arith.add(stock,amendNum);
                        stockMap.put(entity.getProductId(),stock);
                    }
                }
                List<UpdateDataEntity> productUpdateList = new ArrayList<>();
                for (ProductEntityExt entity : productEntityExtList) {
                    Double stock = stockMap.getOrDefault(entity.getId(),0D);
                    if (!Objects.equals(entity.getData().getDouble(ProductEnum.STOCK.getAttr()),stock)){
                        JSONObject data = new JSONObject();
                        data.put(ProductEnum.STOCK.getAttr(),stock);
                        productUpdateList.add(ExplainUtil.getUpdateData(entity.getId(),data,corpid));
                    }
                }

                for (ProductWarehouseEntity entity : allWarehouoseList) {
                    Double stock = stockMap.getOrDefault(entity.getProductId(),0D);
                    if (!Objects.equals(entity.getNum(),stock)){
                        entity.setNum(stock);
                        updateList.add(entity);
                    }
                }
                if (!productUpdateList.isEmpty()){
                    productModel.updateBatch(productUpdateList,corpid);
//                    productNeedUpdateSize += productUpdateList.size();
                }
                if (!updateList.isEmpty()){
                    productWarehouseModel.updateStockBatch(updateList,corpid);
//                    stockNeedUpdateSize += updateList.size();
                }

            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
//        LOG.warn("全仓数据还需要更新的数量:" + stockNeedUpdateSize);
//        LOG.warn("产品数据还需要更新的数量:" + productNeedUpdateSize);
        return "success";
    }

    @RequestMapping(value = "/oppForm", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String oppForm(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        param.put("enable",1);
        param.put("businessType",XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
        List<String> corpidList = companyModel.getCorpidList();
        List<String> enableList = new ArrayList<>();
        int index = 0;
        for (String corpid : corpidList) {
            index++;
            LOG.warn("corpid:" + corpid + "," + index + "/" + corpidList.size());
            param.put(StringConstant.CORPID,corpid);
            Integer count = paasFormModel.getEntitysCount(param);
            if (count > 1){
                enableList.add(corpid);
            }
        }
        LOG.warn("enableList:" + JSONArray.toJSONString(enableList));
        return "success";

    }

    @RequestMapping(value = "/oldPurchase", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String oldPurchase(@RequestBody @Valid JxcStockDTO jxcStockDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(jxcStockDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpList = purchaseProductModel.getCorpidList();
        //跳过质量保证组，数据太多了
        corpList.remove("dinga93c84f4d89688bf35c2f4657eb6378f");
        List<String> msgList = new ArrayList<>();
        for (String corpid : corpList) {
            StringBuilder corpidBuilder = new StringBuilder();
            Long idGte = 0L;
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("pageSize",1000);
            while (true){
                param.put("idGte",idGte);
                param.put("orderByStr","id asc");
                List<PurchaseEntityExt> purchaseEntityExtList = purchaseModel.findEntitys(param);
                if (purchaseEntityExtList.isEmpty()){
                    break;
                }
                idGte = purchaseEntityExtList.get(purchaseEntityExtList.size()-1).getId();
                List<Long> purchaseIdList = new ArrayList<>();
                purchaseEntityExtList.forEach(item -> purchaseIdList.add(item.getId()));
                Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                map.put("corpid",corpid);
                map.put("del",DelEnum.NORMAL.getDel());
                map.put("purchaseSheetIdIn",purchaseIdList);
                map.put("groupByStr","corpid,purchase_sheet_id,product_id");
                map.put("having","count(1) > 1");
                List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductModel.findEntitys(map);
                if (purchaseProductEntityList.isEmpty()){
                    continue;
                }
                Set<Long> purchaseSearchIdList = new HashSet<>();
                List<String> repeatList = new ArrayList<>();
                purchaseProductEntityList.forEach(item -> {
                    purchaseSearchIdList.add(item.getPurchaseSheetId());
                    repeatList.add(item.getPurchaseSheetId() + "_" + item.getProductId());
                });
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                boolQueryBuilder.filter(termQuery("del",DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE),InstockTypeEnum.PURCHASE_INSTOCK.getCode()));
                boolQueryBuilder.filter(termsQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID),purchaseSearchIdList));
                List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK,boolQueryBuilder,PaasFormDataEntityExt.class,null);
                Map<Long,Long> idMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                purchaseSearchIdList.clear();
                paasFormDataEntityExtList.forEach(item -> {
                    idMap.put(item.getId(),item.getData().getLong(InstockEnum.REF_ID.getAttr()));
                    purchaseSearchIdList.add(item.getId());
                });
                map.clear();
                map.put("corpid",corpid);
                map.put("del",DelEnum.NORMAL.getDel());
                map.put("instockIdIn",purchaseSearchIdList);
                List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(map);
                for (InstockProductEntity entity : instockProductEntityList) {
                    String key = idMap.get(entity.getIntoWarehouseId()) + "_" + entity.getProductId();
//                    LOG.warn(key);
                    if (repeatList.contains(key)){
                        if (Objects.isNull(entity.getRefProductId())){
                            corpidBuilder.append(key).append(",");
                        }
                    }
                }

            }
            if (!corpidBuilder.toString().isEmpty()){
                msgList.add(corpid + ":" + corpidBuilder.toString());
            }
        }
        for (String msg : msgList) {
            LOG.warn(msg);
        }
        return null;
    }

    @RequestMapping(value = "/oldWorkOrder", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String oldWorkOrder(@RequestBody @Valid JxcStockDTO jxcStockDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(jxcStockDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpList = workOrderProductModel.getCorpidList();
        //跳过质量保证组，数据太多了
//        corpList.remove("dinga93c84f4d89688bf35c2f4657eb6378f");
        List<String> msgList = new ArrayList<>();
        for (String corpid : corpList) {
            StringBuilder corpidBuilder = new StringBuilder();
            Long idGte = 0L;
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("pageSize",1000);
            while (true){
                param.put("idGte",idGte);
                param.put("orderByStr","id asc");
                List<WorkOrderEntity> workOrderEntityList = workOrderModel.findEntitys(param);
                if (workOrderEntityList.isEmpty()){
                    break;
                }
                idGte = workOrderEntityList.get(workOrderEntityList.size()-1).getId();
                List<Long> purchaseIdList = new ArrayList<>();
                workOrderEntityList.forEach(item -> purchaseIdList.add(item.getId()));
                Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                map.put("corpid",corpid);
                map.put("del",DelEnum.NORMAL.getDel());
                map.put("purchaseSheetIdIn",purchaseIdList);
                map.put("groupByStr","corpid,work_order_id,product_id");
                map.put("having","count(1) > 1");
                List<WorkOrderProductEntity> workOrderProductEntityList = workOrderProductModel.findEntitys(map);
                if (workOrderProductEntityList.isEmpty()){
                    continue;
                }
                Set<Long> workOrderSearchList = new HashSet<>();
                List<String> repeatList = new ArrayList<>();
                workOrderProductEntityList.forEach(item -> {
                    workOrderSearchList.add(item.getWorkOrderId());
                    repeatList.add(item.getWorkOrderId() + "_" + item.getProductId());
                });
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                boolQueryBuilder.filter(termQuery("del",DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE),OutstockTypeEnum.WORK_ORDER_OUTSTOCK.getCode()));
                boolQueryBuilder.filter(termsQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.REF_ID),workOrderSearchList));
                List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK,boolQueryBuilder,PaasFormDataEntityExt.class,null);
                Map<Long,Long> idMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                workOrderSearchList.clear();
                paasFormDataEntityExtList.forEach(item -> {
                    idMap.put(item.getId(),item.getData().getLong(OutstockEnum.REF_ID.getAttr()));
                    workOrderSearchList.add(item.getId());
                });
                map.clear();
                map.put("corpid",corpid);
                map.put("del",DelEnum.NORMAL.getDel());
                map.put("outstockIdIn",workOrderSearchList);
                List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(map);
                for (OutstockProductEntity entity : outstockProductEntityList) {
                    String key = idMap.get(entity.getOutWarehouseId()) + "_" + entity.getProductId();
//                    LOG.warn(key);
                    if (repeatList.contains(key)){
                        if (Objects.isNull(entity.getRefProductId())){
                            corpidBuilder.append(key).append(",");
                        }
                    }
                }

            }
            if (!corpidBuilder.toString().isEmpty()){
                msgList.add(corpid + ":" + corpidBuilder.toString());
            }
        }
        for (String msg : msgList) {
            LOG.warn(msg);
        }
        return null;
    }

    @RequestMapping(value = "/fixWorkOrderRefProductId", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixWorkOrderRefProductId(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpList = workOrderProductModel.getCorpidList();
        for (String corpid : corpList) {
            LOG.warn("fixWorkOrderRefProductId:" + corpid);
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE),OutstockTypeEnum.WORK_ORDER_OUTSTOCK.getCode()));
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK,boolQueryBuilder,PaasFormDataEntityExt.class,null);
            List<Long> outstockIdList = new ArrayList<>();
            Map<Long, Long> idMap = new HashMap<>();
            paasFormDataEntityExtList.forEach(item -> {
                outstockIdList.add(item.getId());
                idMap.put(item.getId(), item.getData().getLong(OutstockEnum.REF_ID.getAttr()));
            });
            //没有refProductId
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("outWarehouseIdIn", outstockIdList);
            List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(param);
            param.clear();
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("columns", "work_order_id,product_id,id");
            List<WorkOrderProductEntity> workOrderProductEntityList = workOrderProductModel.findEntitys(param);
            Map<String, Long> refProductMap = new HashMap<>();
            for (WorkOrderProductEntity entity : workOrderProductEntityList) {
                refProductMap.put(entity.getWorkOrderId() + "_" + entity.getProductId(), entity.getId());
            }
            for (OutstockProductEntity entity : outstockProductEntityList) {
                entity.setRefProductId(refProductMap.get(idMap.get(entity.getOutWarehouseId()) + "_" + entity.getProductId()));
                entity.setUpdateTime(DateTimeUtil.getInt());
            }
            if (!outstockProductEntityList.isEmpty()) {
                outstockProductModel.updateBatch(outstockProductEntityList, corpid);

            }
        }
        return "";
    }

    @RequestMapping(value = "/fixNegStock", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixNegStock(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = productModel.getCorpidList();
        for (String corpid : corpidList){
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            param.put("numLte",0);
            List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(param,null);
            if (productWarehouseEntityList.isEmpty()){
                continue;
            }
            List<Long> dataIdList = new ArrayList<>();
            productWarehouseEntityList.forEach(item -> dataIdList.add(item.getProductId()));
            fixDataJobDTO.setCorpidList(Collections.singletonList(corpid));
            fixDataJobDTO.setCorpid(corpid);
            fixDataJobDTO.setDataIdList(dataIdList);
            fixAllStock(fixDataJobDTO,br);
        }
        return "success";
    }

    @RequestMapping(value = "/oldReturnPurchase", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String oldReturnPurchase(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = purchaseModel.getCorpidList();
        StringBuilder stringBuilder = new StringBuilder();
        int index = 0;
        for (String corpid : corpidList) {
            index++;
            LOG.warn(corpid + ":" + index + "/" + corpidList.size());
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            param.put("addTimeLte",1684201600);
            List<ReturnedPurchaseEntityExt> returnedPurchaseEntityExtList = returnedPurchaseModel.findEntitys(param);
            if (returnedPurchaseEntityExtList.isEmpty()){
                continue;
            }
            for (ReturnedPurchaseEntityExt entityExt : returnedPurchaseEntityExtList) {
                param.clear();
                param.put(StringConstant.CORPID,corpid);
                param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
                param.put("returnPurchaseId",entityExt.getId());
                List<ReturnedPurchaseProductEntity> returnedPurchaseProductEntityList = returnedPurchaseProductModel.findEntitys(param);
                if (!returnedPurchaseProductEntityList.isEmpty() && Objects.isNull(returnedPurchaseProductEntityList.get(0).getRefProductId())){
                    //refProductId 为空表示老数据
                    //查询采购退货单之前的采购入库单
                    param.clear();
                    param.put(StringConstant.CORPID,corpid);
                    param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
                    param.put("type","1");
                    param.put("refId",entityExt.getData().getString(ReturnedPurchaseEnum.PURCHASE_SHEET_ID.getAttr()));
                    param.put("addTimeLte",entityExt.getAddTime());
                    List<InstockEntityExt> instockEntityExtList = instockModel.findEntitys(param);
                    List<Long> instockIdList = new ArrayList<>();
                    instockEntityExtList.forEach(item -> instockIdList.add(item.getId()));
                    param.clear();
                    param.put(StringConstant.CORPID,corpid);
                    param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
                    param.put("instockIdIn",instockIdList);
                    List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(param);
                    Map<Long,Integer> instockProductCountMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (InstockProductEntity entity : instockProductEntityList) {
                        if (instockProductCountMap.containsKey(entity.getProductId())){
                            instockProductCountMap.put(entity.getProductId(),2);
                        }else {
                            instockProductCountMap.put(entity.getProductId(),1);
                        }
                    }
                    //采购退货产品对应多多条，表示要凉
                    for (ReturnedPurchaseProductEntity returnedPurchaseProductEntity : returnedPurchaseProductEntityList) {
                        if (instockProductCountMap.getOrDefault(returnedPurchaseProductEntity.getProductId(),0) > 1){
                            stringBuilder.append(corpid).append(":").append(returnedPurchaseProductEntity.getReturnPurchaseId());
                            break;
                        }
                    }
                }
            }
        }
        LOG.warn(stringBuilder.toString());
        return "success";
    }


    @RequestMapping(value = "/fixAssemble", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixAssemble(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = Arrays.asList("1","ding45b220254ed2e97335c2f4657eb6378f","ding5d3eef98c4e3f1fe4ac5d6980864d335","ding615498363c6eb7c535c2f4657eb6378f","ding6c1313fcb2bb470435c2f4657eb6378f","dingfc7a34ec4e8d767935c2f4657eb6378f");
        long index = 0;
        for (String corpid : corpidList) {
            index ++;
            LOG.warn(corpid + ":" + index + "/" + corpidList.size());
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            param.put("warehouseId",0);
            List<AssembleProductEntity> assembleProductEntityList = assembleProductModel.findEntitys(param);
            if (assembleProductEntityList.isEmpty()) {
                continue;
            }
            List<Long> assembleIdList = new ArrayList<>();
            for (AssembleProductEntity assembleProductEntity : assembleProductEntityList) {
                assembleIdList.add(assembleProductEntity.getAssembleId());
            }
            param.clear();
            param.put(StringConstant.CORPID,corpid);
            param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            param.put("idIn",assembleIdList);
            List<AssembleEntityExt> assembleEntityExtList = assembleModel.findEntitys(param);
            if (assembleEntityExtList.isEmpty()) {
                continue;
            }
            Map<Long,Long> warehouseIdMap = new HashMap<>();
            Map<Long,String> warehouseNameMap = new HashMap<>();
            for (AssembleEntityExt entityExt : assembleEntityExtList) {
                warehouseIdMap.put(entityExt.getId(),entityExt.getData().getLong(AssembleEnum.OUT_WAREHOUSE_ID.getAttr()));
                warehouseNameMap.put(entityExt.getId(),entityExt.getData().getString(AssembleEnum.OUT_WAREHOUSE_ID_LINKED_TEXT.getAttr()));
            }
            //装配单产品更新
            for (AssembleProductEntity entity : assembleProductEntityList) {
                entity.setWarehouseId(warehouseIdMap.get(entity.getAssembleId()));
                JSONObject data = entity.getData();
                data.put(SelectProductEnum.WAREHOUSE.getAttr(),warehouseIdMap.get(entity.getAssembleId()));
                entity.setData(data);
                assembleProductModel.update(entity);
            }
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE),OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode()));
            boolQueryBuilder.filter(termsQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.REF_ID),assembleIdList));
            List<PaasFormDataEntityExt> outstockList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK,boolQueryBuilder,PaasFormDataEntityExt.class,null);
            if (!outstockList.isEmpty()) {
                List<Long> outstockIdList = new ArrayList<>();
                for (PaasFormDataEntityExt entityExt : outstockList) {
                    outstockIdList.add(entityExt.getId());
                }
                param.clear();
                param.put(StringConstant.CORPID,corpid);
                param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
                param.put("outstockIdIn",outstockIdList);
                List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(param);
                //出库单更新
                List<UpdateDataEntity> updateList = new ArrayList<>();
                Map<Long,Long> outWarehouseIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (PaasFormDataEntityExt entityExt : outstockList) {
                    JSONObject data = new JSONObject();
                    data.put(OutstockEnum.WAREHOUSE_ID.getAttr(),warehouseIdMap.get(entityExt.getData().getLong(OutstockEnum.REF_ID.getAttr())));
                    data.put(OutstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(),warehouseNameMap.get(entityExt.getData().getLong(OutstockEnum.REF_ID.getAttr())));
                    updateList.add(ExplainUtil.getUpdateData(entityExt.getId(),data,corpid));
                    outWarehouseIdMap.put(entityExt.getId(),warehouseIdMap.get(entityExt.getData().getLong(OutstockEnum.REF_ID.getAttr())));
                }
                if (!updateList.isEmpty()) {
                    outstockModel.updateBatch(updateList,corpid);
                }
                //出库单产品更新
                List<Long> productIdList = new ArrayList<>();
                for (OutstockProductEntity entity : outstockProductEntityList) {
                    productIdList.add(entity.getProductId());
                    entity.setWarehouseId(outWarehouseIdMap.get(entity.getOutWarehouseId()));
                    JSONObject data = entity.getData();
                    data.put(SelectProductEnum.WAREHOUSE.getAttr(),outWarehouseIdMap.get(entity.getOutWarehouseId()));
                    outstockProductModel.update(entity);
                }
                if (!productIdList.isEmpty()) {
                    //库存重算
                    fixDataJobDTO.setCorpidList(Collections.singletonList(corpid));
                    fixDataJobDTO.setCorpid(corpid);
                    fixDataJobDTO.setDataIdList(productIdList);
                    fixAllStock(fixDataJobDTO,br);
                }
            }
        }
        LOG.warn("fixAssemble OVER");
        return "success";
    }


    @RequestMapping(value = "/fixBatchStock", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixBatchStock(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LOG.warn("fixBatchStock begin");
        //手动可以区分的productId
        List<Integer> productIdList = Arrays.asList(2592467,2592480,2592492,2592506,2592519,2592655,2593949,2593955,2593957,2593959,2593961,2593973,2593975,2593985,2593989,2593991,2593995,2593999,2594001,2594005,2594011,2594015,2594035,2594109,2594133,2594135,2594137,2594139,2594143,2594155,2594157,2594167,2594179,2594621,2594623,2594641,2594643,2594647,2594649,2594651,2594653,2594655,2594657,2594659,2594665,2594667,2594669,2595009,2595015,2595161,2595163,2595165,2595183,2710125,3358631,3358639);
        String corpid = fixDataJobDTO.getCorpid();
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,corpid);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        param.put("productIdIn",productIdList);
        param.put("batch","");
        List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(param);
        if (outstockProductEntityList.isEmpty()) {
            return "pause";
        }
        param.clear();
        param.put(StringConstant.CORPID,corpid);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        param.put("productIdIn",productIdList);
        param.put("warehouseChecked",1);
        List<ProductStockEntity> productStockEntityList = productStockModel.findEntitys(param);
        Map<String,ProductStockEntity> batchKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ProductStockEntity entity : productStockEntityList) {
            batchKeyMap.put(entity.getProductId() + "_" + entity.getWarehouseId(),entity);
        }
        Map<String,Double> updateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (OutstockProductEntity entity : outstockProductEntityList) {
            String batchkey = entity.getProductId() + "_" + entity.getWarehouseId();
            if (batchKeyMap.containsKey(batchkey)) {
                ProductStockEntity productStockEntity = batchKeyMap.get(batchkey);
                entity.setBatch(productStockEntity.getBatch());
                entity.setProduceDate(productStockEntity.getProduceDate());
                entity.setGuaranteePeriod(productStockEntity.getGuaranteePeriod());
                outstockProductModel.update(entity);
                Double num = updateMap.getOrDefault(batchkey,0D);
                num = Arith.add(num,entity.getProductNum());
                updateMap.put(batchkey,num);
            }
        }
        List<ProductStockEntity> updateList = new ArrayList<>();
        for (Map.Entry<String, Double> entry : updateMap.entrySet()) {
            if (batchKeyMap.containsKey(entry.getKey())) {
                ProductStockEntity entity = batchKeyMap.get(entry.getKey());
                entity.setNum(Arith.sub(entity.getNum(),entry.getValue()));
                updateList.add(entity);
            }
        }
        if (!updateList.isEmpty()) {
            productStockModel.updateBatch(updateList,corpid);
        }
        LOG.warn("fixBatchStock over");
        return "success";
    }

    @RequestMapping(value = "/fixProductSpecData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixProductSpecData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        // select  JSON_EXTRACT(`data`, "$.text_10"), count(1) from tb_saas_product where corpid ='ding9ab8ee5bfe81d537'  and del = 0 and serial_no= '3JS-042B' group by  json_extract(`data`,"$.text_10") having count(1) >1 ;
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (Objects.isNull(corpidList) || corpidList.size() != 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "只允许刷一个公司");
        }
        String corpid = corpidList.get(0);
        LOG.warn("fixProductSpeData 开始");
        Long dataId = fixDataJobDTO.getDataId();
        if (Objects.isNull(dataId)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "只允许刷一个产品");
        }
        List<SpecificationEntity> specificationList = specificationModel.getSpecificationList(corpid, dataId);
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), dataId));
        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
        List<PaasFormDataEntity> productList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntity.class, Arrays.asList("id", ProductEnum.getAttrConnectData(ProductEnum.SPECIFICATION_LINK_TEXT)));

        JSONArray specArr = new JSONArray();
        JSONArray addArr = new JSONArray();
        for (int i = 0; i < specificationList.size(); i ++) {
            SpecificationEntity specificationEntity = specificationList.get(i);
            String name = specificationEntity.getName();
            String value = specificationEntity.getValue();
            List<String> specValueList = JSONArray.parseArray(value, String.class);
            if (specArr.isEmpty()) {
                for (String str : specValueList) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(name, str);
                    specArr.add(jsonObject);
                }

            } else {
                addArr.clear();
                for (int j = 0; j  < specArr.size(); j ++) {
                    JSONObject jsonObject = specArr.getJSONObject(j);
                    for (int k = 0 ; k < specValueList.size(); k ++ ) {
                        if (k == 0) {
                            jsonObject.put(name, specValueList.get(k));
                        } else {
                            JSONObject copyJson = (JSONObject) CloneUtil.deepClone(jsonObject);
                            copyJson.put(name, specValueList.get(k));
                            addArr.add(copyJson);
                        }
                    }
                }
                specArr.addAll(addArr);
            }
        }
        for (PaasFormDataEntity paasFormDataEntity : productList) {
            JSONObject specObj = JSONObject.parseObject(paasFormDataEntity.getData().getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()), JSONObject.class, Feature.OrderedField);
            if (!specArr.contains(specObj)) {

            }
        }
        return "success";
    }

    @RequestMapping(value = "/fixOriStockData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixOriStockData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (Objects.isNull(corpidList) || corpidList.size() != 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "只允许刷一个公司");
        }
        String corpid = corpidList.get(0);
        List<Long> dataIdList = fixDataJobDTO.getDataIdList();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("idIn", dataIdList);
        List<WarehouseOristockEntity> warehouseOristockEntityList = warehouseOristockModel.findEntitys(param);
        for (WarehouseOristockEntity entity : warehouseOristockEntityList) {
            Integer insertId = entity.getId();
            PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
            BeanUtil.copyProperties(entity, paasFormDataEntity);
            paasFormDataEntity.setId(insertId.longValue());
            paasFormDataEntity.setData(null);
            InsertDTO insertDTO = paasEsModel.getSaveDTO(paasFormDataEntity, IndexTypeEnum.IDX_SAAS_ORISTOCK);
            paasEsModel.insert(insertDTO);
        }
        return "success";
    }

    @RequestMapping(value = "/fixEnheStockData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixEnheStockData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }

        String corpid = "ding76172ab7811a6cbe";
        Long parentId = 6124118L;
        Long childId = 6124119L;
        ProductEntityExt parentProduct = productModel.getByKey(parentId, corpid);
        ProductEntityExt childProduct = productModel.getByKey(childId, corpid);

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("productId", childId);
        List<ProductWarehouseEntity> productWarehouseList = productWarehouseModel.findEntitysWithWarehouseChecked(param, 1);

        Double totalStock = 0D;
        for (ProductWarehouseEntity productWarehouse : productWarehouseList) {
            Long currentWarehouseId = productWarehouse.getWarehouseId();
            if (currentWarehouseId <= 0) {
                continue;
            }
            param.clear();
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("productId", childId);
            param.put("warehouseId", currentWarehouseId);
            param.put("status", 0);
            List<ProductSerialBalanceEntity> productSerialBalanceList = productSerialBalanceModel.findEntitys(param);
            Integer instockNum = productSerialBalanceList.size();
            productWarehouse.setNum(instockNum.doubleValue());
            productWarehouse.setTotalCost(Arith.mul(productWarehouse.getCost(), productWarehouse.getNum()));
            totalStock = Arith.add(totalStock, productWarehouse.getNum());
        }
        productWarehouseModel.updateStockBatch(productWarehouseList, corpid);

        childProduct.getData().put(ProductEnum.STOCK.getAttr(), totalStock);
        childProduct.setNum(totalStock);
        childProduct.setTotalCost(Arith.mul(childProduct.getCost(), childProduct.getNum()));
        productModel.update(childProduct);
        parentProduct.getData().put(ProductEnum.STOCK.getAttr(), totalStock);
        parentProduct.setNum(totalStock);
        parentProduct.setTotalCost(Arith.mul(parentProduct.getCost(), parentProduct.getNum()));
        productModel.update(parentProduct);

        return "success";
    }

    @RequestMapping(value = "/fixFuliCostData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixFuliCostData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }

        String corpid = "dingdd99216b9379abd835c2f4657eb6378f";
        // Long parentId = 8163157L;
        // 高配型
        Long childId = 8163160L;
        // 8163158-标准型
        // 8163159-舒适型
        // 8163161-豪华型
        Long warehouseId = 22131L;
        Integer productWarehouseId = 4951216;
        Long instockProductId = 1724778L;

        ProductEntityExt childProduct = productModel.getByKey(childId, corpid);

        // 获取入库成本
        InstockProductEntity instockProductEntity = instockProductModel.getByKey(instockProductId, corpid);
        double instockCost = instockProductEntity.getCost();
        // 更新分仓成本
        ProductWarehouseEntity productWarehouse = productWarehouseModel.getByKey(productWarehouseId, corpid);
        productWarehouse.setCost(instockCost);
        productWarehouse.setTotalCost(Arith.mul(productWarehouse.getCost(), productWarehouse.getNum()));
        productWarehouseModel.updateStockBatch(Arrays.asList(productWarehouse), corpid);

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("productId", childId);
        List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(param, 1);

        double totalCost = 0D;
        for (ProductWarehouseEntity productWarehouseEntity : productWarehouseEntityList) {
            Long warehouse = productWarehouseEntity.getWarehouseId();
            if (warehouse > 0) {
                if (Objects.equals(warehouse, warehouseId)) {
                    totalCost = Arith.add(totalCost, Arith.mul(productWarehouse.getCost(), productWarehouse.getNum()));
                } else {
                    totalCost = Arith.add(totalCost, Arith.mul(productWarehouseEntity.getCost(), productWarehouseEntity.getNum()));
                }
            }
        }

        double avgCost = Arith.div(totalCost, childProduct.getNum());
        childProduct.getData().put(ProductEnum.COST.getAttr(), avgCost);
        childProduct.setCost(avgCost);
        childProduct.setTotalCost(Arith.mul(childProduct.getCost(), childProduct.getNum()));
        productModel.update(childProduct);

        return "success";
    }
    /**
     * @Author: wujian
     * @Description: 删除批次信息 dataIdList为tb_saas_product_stock中的主键ID
     * @Date: 下午5:24 2021/6/4
     * @Param: [fixDataJobDTO, br]
     * @return: java.lang.String
     **/
    @RequestMapping(value = "/fixProductBatch", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixProductBatch(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br)throws Exception{
        String corpid = fixDataJobDTO.getCorpid();
        List<Long> idIn = fixDataJobDTO.getDataIdList();
        if (CollectionUtils.isNotEmpty(idIn)){
            productStockDao.deleteByIdIn(corpid, idIn);
            return "success";
        }else {
            return "请输入要删除的批次ID";
        }
    }

    /**
     * @Author: wujian
     * @Description: 采购合同产品解释添加合同编号字段
     * @Date: 下午5:24 2021/9/10
     * @Param: [fixDataJobDTO, br]
     * @return: java.lang.String
     **/
    @RequestMapping(value = "/repairPurchaseExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairPurchaseExplain(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br)throws Exception{
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();

        // 没传入corpidList时 刷全部公司
        if (CollectionsUtil.isEmpty(corpidList)){
            corpidList = companyModel.getJxcCorpidListTemporary();
            // 公司的默认解释  本地暂时不刷
            corpidList.add("0");
        }
        FieldAttrEntity contractNoEntity = InitExplainsHelper.getNewFieldAttrEntity();
        contractNoEntity.setAttr(PurchaseProductEnum.CONTRACT_NO.getAttr());
        contractNoEntity.setAttrName(PurchaseProductEnum.CONTRACT_NO.getAttrName());
        contractNoEntity.setSaasAttr(PurchaseProductEnum.CONTRACT_NO.getSaasAttr());
        contractNoEntity.setFieldType(PurchaseProductEnum.CONTRACT_NO.getFieldType());
        contractNoEntity.setSetType(PurchaseProductEnum.CONTRACT_NO.getSetType());
        contractNoEntity.setDesignEditable(PurchaseProductEnum.CONTRACT_NO.getDesignEditable());
        List<String> forbiddenSetList = new ArrayList<>();
        forbiddenSetList.add(ForbiddenSettingEnum.DISABLE_DEFAULT.getAlias());
        forbiddenSetList.add(ForbiddenSettingEnum.DISABLE_TYPE.getAlias());
        contractNoEntity.setForbiddenSettingList(forbiddenSetList);
        contractNoEntity.setEditable(0);
        contractNoEntity.setShowType(ShowTypeEnum.EDIT.getCode());
        contractNoEntity.setVisible(1);
        contractNoEntity.setRequired(0);
        contractNoEntity.setIsRedundant(0);
        contractNoEntity.setIsForbidden(0);
        LOG.warn("共需更新公司" + corpidList.size() + "家");
        Integer count = 0 ;
        Integer notHaveExplain = 0;
        Integer haveExplain = 0;
        Integer subFormIsNull = 0;
        Integer itemsIsNull = 0;
        List<String> subFormIsNullList = new ArrayList<>();
        List<String> itemsIsNullList = new ArrayList<>();
        // 循环所有公司
        for (String corpid : corpidList) {
            LOG.warn("开始处理corpid: " + corpid);
            count++;
            // 根据corpid以及businessType获取采购合同解释
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainDao.getByBusinessType(XbbRefTypeEnum.PURCHASE.getCode(),corpid, PaasFormTableNameConstant.TB_PAAS_FORM_EXPLAIN);
            // 解释为空的走默认解释
            if (Objects.nonNull(paasFormExplainEntity) && !Objects.equals("[]", paasFormExplainEntity.getExplains())){
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                // 获取产品解释
                if (CollectionsUtil.isNotEmpty(fieldAttrEntityList)){
                    for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
                        if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.PRODUCT.getAttr())){
                            SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                            if (Objects.nonNull(subForm)){
                                List<FieldAttrEntity> items = (List<FieldAttrEntity>) subForm.getItems();
                                List<String> attrList = new ArrayList<>();
                                if (CollectionsUtil.isNotEmpty(items)){
                                    items.forEach(item -> {attrList.add(item.getAttr());});
                                    if (!attrList.contains(contractNoEntity.getAttr())){
                                        items.add(contractNoEntity);
                                        subForm.setItems(items);
                                        paasFormExplainEntity.setExplains(JSONArray.toJSONString(fieldAttrEntityList));
                                        paasFormExplainModel.update(paasFormExplainEntity);
                                        haveExplain++;
                                        LOG.warn("corpid: " + corpid + "已更新完毕！");
                                        LOG.warn("当前已更新" + count + "家公司，当总前进度" + (count + notHaveExplain) + "/" + +corpidList.size());
                                        LOG.warn("有采购合同解释且正常更新的有" + haveExplain + "家公司,采购合同解释为空或已有合同编号解释的的有" + notHaveExplain + "家公司");
                                        break;
                                    }else {
                                        notHaveExplain ++ ;
                                        LOG.warn("corpid: " + corpid + "解释中已有合同编号解释");
                                    }
                                }else {
                                    itemsIsNull ++;
                                    itemsIsNullList.add(corpid);
                                    LOG.warn("corpid: " + corpid + "采购产品解释中subForm的itmes为空！");
                                }
                            }else {
                                subFormIsNull++;
                                subFormIsNullList.add(corpid);
                                LOG.warn("corpid: " + corpid + "采购合同中采购产品的解释的subForm为空！");
                            }
                        }
                    }
                }else {
                    notHaveExplain ++ ;
                    LOG.warn("corpid: " + corpid + "没有采购合同解释！");
                    LOG.warn("当前已处理" + count + "家公司，当总前进度" + count + "/" + +corpidList.size());
                    LOG.warn("有采购合同解释且正常更新的有" + haveExplain + "家公司,采购合同解释为空或已有合同编号解释的的有" + notHaveExplain + "家公司");
                }
            }else {
                notHaveExplain ++ ;
                LOG.warn("corpid: " + corpid + "没有采购合同解释！");
                LOG.warn("当前已处理" + count + "家公司，当总前进度" + count + "/" + +corpidList.size());
                LOG.warn("有采购合同解释且正常更新的有" + haveExplain + "家公司,采购合同解释为空或已有合同编号解释的的有" + notHaveExplain + "家公司");
            }
        }
        // 清除公司id为0的采购合同解释缓存
        paasRedisHelper.removeValue(RedisPrefixConstant.FIELD_EXPLANATION, "0_" + XbbRefTypeEnum.PURCHASE.getCode() + "_0");
        LOG.warn("consume:{}s", (DateTimeUtil.getInt() - start));
        LOG.warn("本次共处理"+ corpidList.size() + "家公司，其中采购合同解释为空或已有合同编号解释的" + notHaveExplain + "家公司,有解释且已更新的共有" + haveExplain + "家！subForm为空的有：" + subFormIsNull + "家！itmes为空的有" + itemsIsNull + "家！");
        LOG.warn("采购产品解释中subForm为空的corpidList为:" + subFormIsNullList);
        LOG.warn("采购产品解释中subForm的itmes为空的corpidList为:" + itemsIsNullList);
        return "success";
    }

    /**
     * @Author: wujian
     * @Description: 回滚 采购合同产品解释添加合同编号字段
     * @Date: 下午5:24 2021/9/10
     * @Param: [fixDataJobDTO, br]
     * @return: java.lang.String
     **/
    @RequestMapping(value = "/rollbackPurchaseExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String rollbackPurchaseExplain(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br)throws Exception{
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();

        // 没传入corpidList时 刷全部公司
        if (CollectionsUtil.isEmpty(corpidList)){
            corpidList = companyModel.getJxcCorpidListTemporary();
            // 公司的默认解释  本地暂时不刷
            corpidList.add("0");
        }
        FieldAttrEntity contractNoEntity = InitExplainsHelper.getNewFieldAttrEntity();
        contractNoEntity.setAttr(PurchaseProductEnum.CONTRACT_NO.getAttr());
        LOG.warn("共需更新公司" + corpidList.size() + "家");
        Integer count = 0 ;
        Integer notHaveExplain = 0;
        Integer haveExplain = 0;
        Integer subFormIsNull = 0;
        Integer itemsIsNull = 0;
        List<String> subFormIsNullList = new ArrayList<>();
        List<String> itemsIsNullList = new ArrayList<>();
        // 循环所有公司
        for (String corpid : corpidList) {
            LOG.warn("开始处理corpid: " + corpid);
            count++;
            // 根据corpid以及businessType获取采购合同解释
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainDao.getByBusinessType(XbbRefTypeEnum.PURCHASE.getCode(),corpid, PaasFormTableNameConstant.TB_PAAS_FORM_EXPLAIN);
            // 解释为空的走默认解释
            if (Objects.nonNull(paasFormExplainEntity) && !Objects.equals("[]", paasFormExplainEntity.getExplains())){
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                // 获取产品解释
                if (CollectionsUtil.isNotEmpty(fieldAttrEntityList)){
                    for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
                        if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.PRODUCT.getAttr())){
                            SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                            if (Objects.nonNull(subForm)){
                                List<FieldAttrEntity> items = (List<FieldAttrEntity>) subForm.getItems();
                                List<String> attrList = new ArrayList<>();
                                if (CollectionsUtil.isNotEmpty(items)){
                                    items.forEach(item -> {attrList.add(item.getAttr());});
                                    // 如果包含 则移除该字段解释
                                    if (attrList.contains(contractNoEntity.getAttr())){
                                        Iterator<FieldAttrEntity> iterator = items.iterator();
                                        while (iterator.hasNext()){
                                            FieldAttrEntity next = iterator.next();
                                            if (Objects.equals(next.getAttr(),contractNoEntity.getAttr())){
                                                iterator.remove();
                                            }
                                        }
                                        subForm.setItems(items);
                                        paasFormExplainEntity.setExplains(JSONArray.toJSONString(fieldAttrEntityList));
                                        paasFormExplainModel.update(paasFormExplainEntity);
                                        haveExplain++;
                                        LOG.warn("corpid: " + corpid + "已更新完毕！");
                                        LOG.warn("当前已处理" + count + "家公司，当总前进度" + (count + notHaveExplain) + "/" + +corpidList.size());
                                        LOG.warn("有采购合同解释且正常更新的有" + haveExplain + "家公司,没有采购合同解释的有" + notHaveExplain + "家公司");
                                        break;
                                    }
                                }else {
                                    itemsIsNull ++;
                                    itemsIsNullList.add(corpid);
                                    LOG.warn("corpid: " + corpid + "采购产品解释中subForm的itmes为空！");
                                }
                            }else {
                                subFormIsNull++;
                                subFormIsNullList.add(corpid);
                                LOG.warn("corpid: " + corpid + "采购合同中采购产品的解释的subForm为空！");
                            }
                        }
                    }
                }else {
                    notHaveExplain ++ ;
                    LOG.warn("corpid: " + corpid + "没有采购合同解释！");
                    LOG.warn("当前已处理" + count + "家公司，当总前进度" + count + "/" + +corpidList.size());
                    LOG.warn("有采购合同解释且正常更新的有" + haveExplain + "家公司,没有采购合同解释的有" + notHaveExplain + "家公司");
                }
            }else {
                notHaveExplain ++ ;
                LOG.warn("corpid: " + corpid + "没有采购合同解释！");
                LOG.warn("当前已处理" + count + "家公司，当总前进度" + count + "/" + +corpidList.size());
                LOG.warn("有采购合同解释且正常更新的有" + haveExplain + "家公司,没有采购合同解释的有" + notHaveExplain + "家公司");
            }
        }
        // 清除公司id为0的采购合同解释缓存
        paasRedisHelper.removeValue(RedisPrefixConstant.FIELD_EXPLANATION, "0_" + XbbRefTypeEnum.PURCHASE.getCode() + "_0");
        LOG.warn("consume:{}s", (DateTimeUtil.getInt() - start));
        LOG.warn("本次共处理"+ corpidList.size() + "家公司，其中采购合同解释为空或已有合同编号解释的" + notHaveExplain + "家公司,有解释且已更新的共有" + haveExplain + "家！subForm为空的有：" + subFormIsNull + "家！itmes为空的有" + itemsIsNull + "家！");
        LOG.warn("采购产品解释中subForm为空的corpidList为:" + subFormIsNullList);
        LOG.warn("采购产品解释中subForm的itmes为空的corpidList为:" + itemsIsNullList);
        return "success";
    }

    /**
     * @Author: wujian
     * @Description: 初始化智能补货脚本数据
     * @Date: 下午7:21 2021/11/15
     * @Param: [fixDataJobDTO, br]
     * @return: java.lang.String
     **/
    @RequestMapping(value = "/repairSmartReplenishmentData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairSmartReplenishmentData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br)throws Exception{
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)){
           // 刷全公司的
            corpidList = productModel.getCorpidList();
        }
        List<String> excludeCorpidList = fixDataJobDTO.getExclude();
        boolean haveExclude = CollectionUtils.isNotEmpty(excludeCorpidList);
        LOG.warn("共需更新公司" + corpidList.size() + "家");
        Integer count = 0;
        for (String corpid : corpidList) {
            count++;
            if (haveExclude && excludeCorpidList.contains(corpid)){
                continue;
            }
            Long idGte = 0L;
            while (true) {
            // 拿出该公司下的所有没删除的产品
            Map<String, Object> param = new HashMap<>();
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("dataParentIdGte", 0L);
            param.put("idGte", idGte);
            param.put("pageSize", 1000);
            param.put("orderByStr", "id asc");
            List<ProductEntityExt> productEntityExtList = productModel.findEntitys(param);
            if (productEntityExtList.isEmpty()) {
                break;
            }
            //每次查询出来最大的产品ID
            idGte = productEntityExtList.get(productEntityExtList.size() - 1).getId();
            //组装产品ID集合
            List<Long> productIdList = new ArrayList<>();
            if (CollectionsUtil.isNotEmpty(productEntityExtList)) {
                productEntityExtList.forEach(item -> productIdList.add(item.getId()));
            }
            Map<String, Object> warehouseParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            warehouseParam.put("corpid", corpid);
            warehouseParam.put("del", DelEnum.NORMAL.getDel());
            warehouseParam.put("productIdIn", productIdList);
            warehouseParam.put("warehouseId", 0);
            List<ProductWarehouseEntity> warehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(warehouseParam, BasicConstant.ONE);
            // 封装产品预警map key=productId value = 预警下限
            Map<Long, Double> productWarehouseEntityMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(warehouseEntityList)) {
                warehouseEntityList.forEach(item -> productWarehouseEntityMap.put(item.getProductId(), item.getStockLowerLimit() == null ? 0D:item.getStockLowerLimit()));
            }
            // 获取合同产品数据
            Map<String, Object> contractProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            contractProductParam.put("corpid", corpid);
            contractProductParam.put("del", DelEnum.NORMAL.getDel());
            contractProductParam.put("isProduce", ContractProduceEnum.WAIT_PURCHASE.getCode());
            contractProductParam.put("productIdIn", productIdList);
            List<ContractProductEntity> contractProductEntityList = contractProductModel.findEntitys(contractProductParam);
            Map<Long, Double> productWaitOutstockNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionsUtil.isNotEmpty(contractProductEntityList)) {
                for (ContractProductEntity contractProductEntity : contractProductEntityList) {
                    Long productId = contractProductEntity.getProductId();
                    if (productWaitOutstockNumMap.containsKey(productId)) {
                        productWaitOutstockNumMap.put(productId, Arith.add(productWaitOutstockNumMap.get(productId), Arith.sub(contractProductEntity.getProductNum(), contractProductEntity.getOutstockNum())));
                    } else {
                        productWaitOutstockNumMap.put(productId, Arith.sub(contractProductEntity.getProductNum(), contractProductEntity.getOutstockNum()));
                    }
                }
            }
            // 看公司是否开启工作流
            boolean openWorkFlow = commonHelp.isOpenWorkFlow(corpid);
            // 获取采购合同数据
            Map<String, Object> purchaseProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            purchaseProductParam.put("corpid", corpid);
            purchaseProductParam.put("del", DelEnum.NORMAL.getDel());
            purchaseProductParam.put("productIdIn", productIdList);
            List<PurchaseProductEntity> purchaseProductList = purchaseProductModel.findEntitys(purchaseProductParam);
            Map<Long, Double> pendingInstockNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionsUtil.isNotEmpty(purchaseProductList)) {
                for (PurchaseProductEntity entity : purchaseProductList) {
                    Long productId = entity.getProductId();
                    if (pendingInstockNumMap.containsKey(productId)) {
                        pendingInstockNumMap.put(productId, Arith.add(pendingInstockNumMap.get(productId), Arith.sub(entity.getProductNum(), entity.getInstockNum())));
                    } else {
                        pendingInstockNumMap.put(productId, Arith.sub(entity.getProductNum(), entity.getInstockNum()));
                    }

                }
            }
            // 工作流审批中的采购入库数量
            Map<Long,Double> purchaseInstockProductNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 工作流审批中的销售出库数量
            Map<Long,Double> outNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 查询工作流审批中的采购入库数量
            if (openWorkFlow){
                // 开启工作流的需要减掉审批中的采购入库
                Map<String,Object> purchaseInstockParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                purchaseInstockParam.put("corpid",corpid);
                purchaseInstockParam.put("del",DelEnum.NORMAL.getDel());
                purchaseInstockParam.put("flowStatusIn",FlowStatusEnum.inApproval());
                // 审批中的入库单
                List<InstockEntityExt> instockEntityExts = instockModel.findEntitysWithoutSub(purchaseInstockParam);
                List<Long> instockIdList = new ArrayList<>();

                if (CollectionUtils.isNotEmpty(instockEntityExts)){
                    instockEntityExts.forEach(item -> instockIdList.add(item.getId()));
                    // 查询type为采购入库单的入库产品
                    Map<String,Object> purchaseInstockProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    purchaseInstockProductParam.put("corpid",corpid);
                    purchaseInstockProductParam.put("del",DelEnum.NORMAL.getDel());
                    purchaseInstockProductParam.put("type", InstockTypeEnum.PURCHASE_INSTOCK.getCode());
                    purchaseInstockProductParam.put("intoWarehouseIdIn",instockIdList);
                    List<InstockProductEntity> purchaseInstockProductList = instockProductModel.findEntitys(purchaseInstockProductParam);
                    if (CollectionUtils.isNotEmpty(purchaseInstockProductList)){
                        for (InstockProductEntity entity : purchaseInstockProductList) {
                            Long productId = entity.getProductId();
                            Double productNum = entity.getProductNum();
                            if (purchaseInstockProductNumMap.containsKey(productId)){
                                purchaseInstockProductNumMap.put(productId,Arith.add(purchaseInstockProductNumMap.get(productId),productNum));
                            }else {
                                purchaseInstockProductNumMap.put(productId,productNum);
                            }
                        }
                    }
                }
                // 查询出审批中或者待审批的销售出库单
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_OUTSTOCK.getType()));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(StringConstant.FLOW_STATUS,FlowStatusEnum.inApproval()));
                // type 为销售出库单的
                boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE),OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode()));
                List<String> fieldList = new ArrayList<>();
                fieldList.add(StringConstant.DATA_ID);
                List<Long> dataIdList = new ArrayList<>();
                List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
                if (CollectionUtils.isNotEmpty(paasFormDataEntityExtList)){
                    paasFormDataEntityExtList.forEach(item -> dataIdList.add(item.getDataId()));
                }
                if (CollectionUtils.isNotEmpty(dataIdList)){
                    Map<String,Object> workFlowParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    workFlowParam.put("corpid" , corpid);
                    workFlowParam.put("del",DelEnum.NORMAL.getDel());
                    workFlowParam.put("dataIdIn",dataIdList);
                    workFlowParam.put("operate",WorkflowOperateEnum.ADD.getType());
                    workFlowParam.put("columns"," data_id , operate ,corpid ");
                    List<WorkflowTransferDataEntity> entities = workflowTransferDataModel.findEntities(workFlowParam);
                    Set<Long> addIdList = new HashSet<>();
                    if (CollectionUtils.isNotEmpty(entities)){
                        entities.forEach(item -> addIdList.add(item.getDataId()));
                    }
                    if (CollectionUtils.isNotEmpty(addIdList)){
                        List<OutstockProductEntity> productsByOutstockIdIn = outstockProductModel.getProductsByOutstockIdIn(corpid, new ArrayList<>(addIdList));
                        if (CollectionUtils.isNotEmpty(productsByOutstockIdIn)){
                            for (OutstockProductEntity outstockProductEntity : productsByOutstockIdIn) {
                                Long productId = outstockProductEntity.getProductId();
                                Double productNum = outstockProductEntity.getProductNum();
                                if (outNumMap.containsKey(productId)){
                                    outNumMap.put(productId,Arith.add(outNumMap.get(productId),productNum));
                                }else {
                                    outNumMap.put(productId,productNum);
                                }
                            }
                        }
                    }

                }
            }

            List<SmartReplenishmentEntity> smartReplenishmentEntityList = new ArrayList<>();
            for (ProductEntityExt productEntityExt : productEntityExtList) {
                JSONObject data = productEntityExt.getData();
                Long parentId = data.getLong(ProductEnum.PARENT_ID.getAttr());
                // 过滤掉父产品
                if (Objects.equals(0L, parentId)) {
                    continue;
                }
                Long productId = productEntityExt.getId();
                Long now = DateTimeUtil.getInt();
                SmartReplenishmentEntity smartReplenishmentEntity = new SmartReplenishmentEntity();
                smartReplenishmentEntity.setCorpid(corpid);
                smartReplenishmentEntity.setProductId(productId);
                smartReplenishmentEntity.setProductName(data.getString(ProductEnum.NAME.getAttr()));
                smartReplenishmentEntity.setProductNo(productEntityExt.getSerialNo());
                smartReplenishmentEntity.setParentProductId(parentId);
                smartReplenishmentEntity.setDel(DelEnum.NORMAL.getDel());
                smartReplenishmentEntity.setAddTime(productEntityExt.getAddTime());
                smartReplenishmentEntity.setUpdateTime(productEntityExt.getUpdateTime());
                // 库存数量
                Double stock = data.getDouble(ProductEnum.STOCK.getAttr()) == null ? 0D : data.getDouble(ProductEnum.STOCK.getAttr());
                smartReplenishmentEntity.setStockNum(stock);
                // 未出库数量
                if (openWorkFlow){
                    Double outNum = outNumMap.getOrDefault(productId, 0D);
                    Double waitOutNum = productWaitOutstockNumMap.getOrDefault(productId, 0D);
                    smartReplenishmentEntity.setWaitOutstockNum(Arith.sub(waitOutNum,outNum));
                }else {
                    smartReplenishmentEntity.setWaitOutstockNum(productWaitOutstockNumMap.getOrDefault(productId,0D));
                }
                // 待入库数量
                Double pendingInstockNum = pendingInstockNumMap.getOrDefault(productId,0D);
                // 开启了工作流需要减掉审批中的采购入库数量
                if (openWorkFlow){
                    Double approvalNum = purchaseInstockProductNumMap.getOrDefault(productId, 0D);
                    pendingInstockNum = Arith.sub(pendingInstockNum,approvalNum);
                }
                smartReplenishmentEntity.setPendingInstockNum(pendingInstockNum);
                // 最低库存
                smartReplenishmentEntity.setMiniNum(productWarehouseEntityMap.getOrDefault(productId,0D));
                smartReplenishmentEntityList.add(smartReplenishmentEntity);
            }
            if (CollectionUtils.isNotEmpty(smartReplenishmentEntityList)){
                smartReplenishmentModel.insertBatch(smartReplenishmentEntityList);
            }
        }
            LOG.warn("corpid: " + corpid + "已更新完毕！");
            LOG.warn("当前已更新" + count + "家公司，当总前进度" + count + "/" + +corpidList.size());
        }
        LOG.warn("consume:{}s", (DateTimeUtil.getInt() - start));
        return "success";
    }

    /**
     * @Author: wujian
     * @Description: 修复采购结存数据 / 以销定购建议采购量
     * @Date: 下午2:19 2021/12/2
     * 注意：此脚本只能将智能补货数量修复至当前时刻的数据
     * 例如超发库存数量 和采购结存量 都以当前时刻为准 可能和客户想要的不一致 慎用
     * @Param: [fixDataJobDTO, br]
     * @return: java.lang.String
     **/
    @RequestMapping(value = "/repairPurchaseBalanceData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairPurchaseBalanceData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br)throws Exception{
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        String corpid = fixDataJobDTO.getCorpid();
        // 需要修复的合同id集合
        List<Long> dataIdList = fixDataJobDTO.getDataIdList();
        if (CollectionsUtil.isEmpty(dataIdList)){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "必须传入需要刷的合同ID");
        }
        Map<String ,Object> contractParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        contractParam.put("corpid",corpid);
        contractParam.put("del",DelEnum.NORMAL.getDel());
        contractParam.put("isProduce", ContractProduceEnum.WAIT_PURCHASE.getCode());
        contractParam.put("contractIdIn", dataIdList);
        // 查询出所有合同产品数据
        List<ContractProductEntity> contractProductEntityList = contractProductModel.findEntitys(contractParam);
        // 封装出库总量 key=onlyKey  value=出库总量
        Map<String,Double> outstockNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if(CollectionsUtil.isNotEmpty(contractProductEntityList)){
            for (ContractProductEntity contractProductEntity : contractProductEntityList) {
                Long contractId = contractProductEntity.getContractId();
                Long productId = contractProductEntity.getProductId();
                String onlyKey = contractProductEntity.getId() + "_" + productId;
                Double outstockNum = contractProductEntity.getOutstockNum();
                if (outstockNumMap.containsKey(onlyKey)){
                    outstockNumMap.put(onlyKey,Arith.add(outstockNumMap.get(onlyKey),outstockNum));
                }else {
                    outstockNumMap.put(onlyKey,outstockNum);
                }
            }
        }
        // 查询出采购合同产品表数据 封装采购总量
        Map<String ,Object> purchaseProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        purchaseProductParam.put("corpid",corpid);
        purchaseProductParam.put("del",DelEnum.NORMAL.getDel());
        purchaseProductParam.put("contractIdIn", dataIdList);
        List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductModel.findEntitys(purchaseProductParam);
        // key=onlykey   value=采购总量
        Map<String, Double> purchaseNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionsUtil.isNotEmpty(purchaseProductEntityList)){
            for (PurchaseProductEntity entity : purchaseProductEntityList) {
                Long contractId = entity.getContractId();
                Long productId = entity.getProductId();
                String onlyKey = entity.getContractProductId() + "_" + productId;
                Double productNum = entity.getProductNum();
                if (purchaseNumMap.containsKey(onlyKey)){
                    purchaseNumMap.put(onlyKey,Arith.add(purchaseNumMap.get(onlyKey),productNum));
                }else {
                    purchaseNumMap.put(onlyKey,productNum);
                }
            }
        }

        Map<String ,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid",corpid);
        param.put("del",DelEnum.NORMAL.getDel());
        param.put("contractIdIn", dataIdList);
        // 查询出这些采购结存数据
        List<PurchaseBalanceEntity> purchaseBalanceEntityList = purchaseBalanceModel.findEntitys(param);
        if (CollectionsUtil.isNotEmpty(purchaseBalanceEntityList)){
            List<PurchaseBalanceEntity> updateList = new ArrayList<>();
            for (PurchaseBalanceEntity entity : purchaseBalanceEntityList) {
                String onlyKey = entity.getOnlyKey();
                Double outstockNum = Objects.isNull(outstockNumMap.get(onlyKey)) ? 0D:outstockNumMap.get(onlyKey);
                Double purchaseNum = Objects.isNull(purchaseNumMap.get(onlyKey)) ? 0D:purchaseNumMap.get(onlyKey);
                // 如果采购总量大于出库总量 则说明全部从采购里面出库的 超发更新为0 结存更新为采购总量-出库总量
                if (purchaseNum >= outstockNum){
                    entity.setExceedStockNum(0D);
                    entity.setBalanceNum(Arith.sub(purchaseNum,outstockNum));
                }else {
                    entity.setBalanceNum(0D);
                    entity.setExceedStockNum(Arith.sub(outstockNum,purchaseNum));
                }
                updateList.add(entity);
            }
            if (CollectionUtils.isNotEmpty(updateList)){
                purchaseBalanceModel.updateBatch(updateList,corpid);
            }
        }
        return "success";
    }

    /**
     * @Author: wujian
     * @Description: 修复智能补货表数据
     * @Date: 下午2:20 2021/12/2
     * @Param: [fixDataJobDTO, br]
     * @return: java.lang.String
     **/
    @RequestMapping(value = "/repairSmartReplenishment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairSmartReplenishmet(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br)throws Exception{
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        List<Long> productIdList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(fixDataJobDTO.getDataIdList())){
            productIdList = fixDataJobDTO.getDataIdList();
        }
        if (CollectionsUtil.isNotEmpty(corpidList)){
            for (String corpid : corpidList) {
                // 看公司是否开启工作流
                boolean openWorkFlow = commonHelp.isOpenWorkFlow(corpid);
                // 拿出该公司下的所有没删除的产品
                Map<String, Object> param = new HashMap<>();
                param.put("corpid",corpid);
                param.put("del",DelEnum.NORMAL.getDel());
                if (CollectionUtils.isNotEmpty(productIdList)){
                    param.put("idIn",productIdList);
                }
                List<ProductEntityExt> productEntityExtList = productModel.findEntitys(param);
                // 封装库存数量map
                Map<Long,Double> productStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if (CollectionsUtil.isNotEmpty(productEntityExtList)){
                    for (ProductEntityExt item : productEntityExtList) {
                        productIdList.add(item.getId());
                        JSONObject data = item.getData();
                        if (Objects.nonNull(data) && !Objects.equals(0L,data.getLong(ProductEnum.PARENT_ID.getAttr()))){
                            Object stockNum = Objects.isNull(data.get(ProductEnum.STOCK.getAttr())) ? 0D : data.get(ProductEnum.STOCK.getAttr());
                            productStockMap.put(item.getId(),Double.valueOf(stockNum.toString()));
                        }
                    }
                }
                Map<String,Object> warehouseParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                warehouseParam.put("corpid",corpid);
                warehouseParam.put("del",DelEnum.NORMAL.getDel());
                warehouseParam.put("producIdIn",productIdList);
                warehouseParam.put("warehouseId",0);
                List<ProductWarehouseEntity> warehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(warehouseParam, BasicConstant.ONE);
                // 封装产品预警map key=productId value = 预警下限
                Map<Long,Double> productWarehouseEntityMap = new HashMap<>();
                if (CollectionsUtil.isNotEmpty(warehouseEntityList)){
                    warehouseEntityList.forEach(item -> productWarehouseEntityMap.put(item.getProductId(),item.getStockLowerLimit()));
                }
                // 获取合同产品数据
                Map<String,Object> contractProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                contractProductParam.put("corpid",corpid);
                contractProductParam.put("del",DelEnum.NORMAL.getDel());
                contractProductParam.put("productIdIn",productIdList);
                contractProductParam.put("status",0);
                List<ContractProductEntity> contractProductEntityList = contractProductModel.findEntitys(contractProductParam);
                Map<Long,Double> productWaitOutstockNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if (CollectionsUtil.isNotEmpty(contractProductEntityList)){
                    for (ContractProductEntity contractProductEntity : contractProductEntityList) {
                        Long productId = contractProductEntity.getProductId();
                        if (productWaitOutstockNumMap.containsKey(productId)){
                            productWaitOutstockNumMap.put(productId,Arith.add(productWaitOutstockNumMap.get(productId),Arith.sub(contractProductEntity.getProductNum(), contractProductEntity.getOutstockNum())));
                        }else {
                            productWaitOutstockNumMap.put(productId, Arith.sub(contractProductEntity.getProductNum(), contractProductEntity.getOutstockNum()));
                        }
                    }
                }
                // 获取采购合同数据
                Map<String,Object> purchaseProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                purchaseProductParam.put("corpid",corpid);
                purchaseProductParam.put("del",DelEnum.NORMAL.getDel());
                purchaseProductParam.put("productIdIn",productIdList);
                List<PurchaseProductEntity> purchaseProductList = purchaseProductModel.findEntitys(purchaseProductParam);
                Map<Long,Double> pendingInstockNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if (CollectionsUtil.isNotEmpty(purchaseProductList)){
                    for (PurchaseProductEntity entity : purchaseProductList) {
                        Long productId = entity.getProductId();
                        if (pendingInstockNumMap.containsKey(productId)){
                            pendingInstockNumMap.put(productId,Arith.add(pendingInstockNumMap.get(productId),Arith.sub(entity.getProductNum(),entity.getInstockNum())));
                        }else {
                            pendingInstockNumMap.put(productId,Arith.sub(entity.getProductNum(),entity.getInstockNum()));
                        }

                    }
                }
                // 工作流审批中的采购入库数量
                Map<Long,Double> purchaseInstockProductNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                // 工作流审批中的销售出库数量
                Map<Long,Double> outNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                // 查询工作流审批中的采购入库数量
                if (openWorkFlow){
                    // 开启工作流的需要减掉审批中的采购入库
                    Map<String,Object> purchaseInstockParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    purchaseInstockParam.put("corpid",corpid);
                    purchaseInstockParam.put("columns","id");
                    purchaseInstockParam.put("del",DelEnum.NORMAL.getDel());
                    purchaseInstockParam.put("flowStatusIn",FlowStatusEnum.inApproval());
                    // 审批中的入库单
                    List<InstockEntityExt> instockEntityExts = instockModel.findEntitys(purchaseInstockParam);
                    List<Long> instockIdList = new ArrayList<>();

                    if (CollectionUtils.isNotEmpty(instockEntityExts)){
                        instockEntityExts.forEach(item -> instockIdList.add(item.getId()));
                        // 查询type为采购入库单的入库产品
                        Map<String,Object> purchaseInstockProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        purchaseInstockProductParam.put("corpid",corpid);
                        purchaseInstockProductParam.put("del",DelEnum.NORMAL.getDel());
                        purchaseInstockProductParam.put("type", InstockTypeEnum.PURCHASE_INSTOCK.getCode());
                        purchaseInstockProductParam.put("intoWarehouseIdIn",instockIdList);
                        List<InstockProductEntity> purchaseInstockProductList = instockProductModel.findEntitys(purchaseInstockProductParam);
                        if (CollectionUtils.isNotEmpty(purchaseInstockProductList)){
                            for (InstockProductEntity entity : purchaseInstockProductList) {
                                Long productId = entity.getProductId();
                                Double productNum = entity.getProductNum();
                                if (purchaseInstockProductNumMap.containsKey(productId)){
                                    purchaseInstockProductNumMap.put(productId,Arith.add(purchaseInstockProductNumMap.get(productId),productNum));
                                }else {
                                    purchaseInstockProductNumMap.put(productId,productNum);
                                }
                            }
                        }
                    }
                    // 查询出审批中或者待审批的销售出库单
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_OUTSTOCK.getType()));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                    boolQueryBuilder.filter(termsQuery(StringConstant.FLOW_STATUS,FlowStatusEnum.inApproval()));
                    // type 为销售出库单的
                    boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE),OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode()));
                    List<String> fieldList = new ArrayList<>();
                    fieldList.add(StringConstant.DATA_ID);
                    List<Long> dataIdList = new ArrayList<>();
                    List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
                    if (CollectionUtils.isNotEmpty(paasFormDataEntityExtList)){
                        paasFormDataEntityExtList.forEach(item -> dataIdList.add(item.getDataId()));
                    }
                    if (CollectionUtils.isNotEmpty(dataIdList)){
                        Map<String,Object> workFlowParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        workFlowParam.put("corpid" , corpid);
                        workFlowParam.put("del",DelEnum.NORMAL.getDel());
                        workFlowParam.put("dataIdIn",dataIdList);
                        workFlowParam.put("operate",WorkflowOperateEnum.ADD.getType());
                        workFlowParam.put("columns"," data_id , operate ,corpid ");
                        List<WorkflowTransferDataEntity> entities = workflowTransferDataModel.findEntities(workFlowParam);
                        Set<Long> addIdList = new HashSet<>();
                        if (CollectionUtils.isNotEmpty(entities)){
                            entities.forEach(item -> addIdList.add(item.getDataId()));
                        }
                        if (CollectionUtils.isNotEmpty(addIdList)){
                            List<OutstockProductEntity> productsByOutstockIdIn = outstockProductModel.getProductsByOutstockIdIn(corpid, new ArrayList<>(addIdList));
                            if (CollectionUtils.isNotEmpty(productsByOutstockIdIn)){
                                for (OutstockProductEntity outstockProductEntity : productsByOutstockIdIn) {
                                    Long productId = outstockProductEntity.getProductId();
                                    Double productNum = outstockProductEntity.getProductNum();
                                    if (outNumMap.containsKey(productId)){
                                        outNumMap.put(productId,Arith.add(outNumMap.get(productId),productNum));
                                    }else {
                                        outNumMap.put(productId,productNum);
                                    }
                                }
                            }
                        }

                    }
                }

                // 根据productIdList 查询出所有智能补货数据
                List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid, productIdList);
                if (CollectionsUtil.isNotEmpty(smartReplenishmentEntityList)){
                    for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                        Long productId = smartReplenishmentEntity.getProductId();
                        Double pendingInstockNum=pendingInstockNumMap.getOrDefault(productId,0D);
                        // 开启了工作流需要减掉审批中的采购入库数量
                        if (openWorkFlow){
                            Double approvalNum = purchaseInstockProductNumMap.getOrDefault(productId, 0D);
                            pendingInstockNum = Arith.sub(pendingInstockNum,approvalNum);
                        }
                        Double miniStock= productWarehouseEntityMap.getOrDefault(productId,0D);
                        Double stockNum= productStockMap.getOrDefault(productId,0D);
                        // 未出库数量
                        if (openWorkFlow){
                            Double outNum = outNumMap.getOrDefault(productId, 0D);
                            Double waitOutNum = productWaitOutstockNumMap.getOrDefault(productId, 0D);
                            smartReplenishmentEntity.setWaitOutstockNum(Arith.sub(waitOutNum,outNum));
                        }else {
                            smartReplenishmentEntity.setWaitOutstockNum(productWaitOutstockNumMap.getOrDefault(productId,0D));
                        }
                        smartReplenishmentEntity.setPendingInstockNum(pendingInstockNum);
                        smartReplenishmentEntity.setMiniNum(miniStock);
                        smartReplenishmentEntity.setStockNum(stockNum);
                    }
                    if (CollectionUtils.isNotEmpty(smartReplenishmentEntityList)){
                        smartReplenishmentModel.updateBatch(smartReplenishmentEntityList,corpid);
                    }
                }
            }
        }
        return "success";
    }


    /**
     * @Author: ruansicheng
     * @Description: 修复库存流水---恢复指定某个日期之后的数据addTimeStart
     * @Date: 下午5:24 2021/10/27
     * @Param: [fixDataJobDTO, br]
     * @return: java.lang.String
     **/
    @RequestMapping(value = "/fixStockFlowBill", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @Transactional
    public String fixStockFlowBill(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        //指定日期必传
        if (Objects.isNull(fixDataJobDTO.getDay())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, "指定日期必传,不能为空");
        }
        List<String> corpidList = new ArrayList<>();
        //支持指定单个或多个公司
        if (!CollectionsUtil.isEmpty(fixDataJobDTO.getCorpidList())) {
            corpidList = fixDataJobDTO.getCorpidList();
        } else if (Objects.nonNull(fixDataJobDTO.getCorpid())) {
            corpidList.add(fixDataJobDTO.getCorpid());
        } else {
            //获取符合条件的公司-现在开启流水的公司列表
            Map<String, Object> param = new HashMap<>();
            //获取符合条件的公司-现在开启流水的公司列表
            param.put("del", 0);
            param.put("configAlias", "enableStockFlowBill");
            param.put("configValue",1);
            List<CompanyConfigEntity> companyConfigEntities = companyConfigModel.findEntitys(param);
            corpidList = companyConfigEntities.stream().map(CompanyConfigEntity::getCorpid).collect(Collectors.toList());
        }
        //指定日期
        //long begainDate = fixDataJobDTO.getAddTimeStart();
        //开始处理数据
        FlowBillInsertDTO flowBillInsertDTO = new FlowBillInsertDTO();
        Map<String, Object> param=new HashMap<>();
        //单位秒
        long day=fixDataJobDTO.getDay();
        Long beforeSeconds=day*86400L;
        Long todayInt = DateTimeUtil.getTodayInt();
        Long greaterThanDate= todayInt - beforeSeconds;
        param.put("greaterThanDate",greaterThanDate);
        LOG.info("一共有"+corpidList.size()+"家公司");
        for (String corpid : corpidList) {
            long start = DateTimeUtil.getInt();
            flowBillInsertDTO.setCorpid(corpid);
            flowBillInsertDTO.setBeforeSeconds(beforeSeconds);
            // 先删除后添加
            param.put("corpid",corpid);
            stockFlowBillModel.deleteByAddTime(param);
            stockSurplusRecordModel.deleteByAddTime(param);
            stockFlowBillService.insertMonthBeforeStockFlow(flowBillInsertDTO);
            batchFlowBillModel.deleteByAddTime(param);
            batchSurplusRecordModel.deleteByAddTime(param);
            batchFlowBillService.insertMonthBeforeBatchFlow(flowBillInsertDTO);

            LOG.warn(corpid+"consume:{}s", (DateTimeUtil.getInt() - start));
            LOG.warn(corpid+"success");

        }
        return "success";
    }

    /**
     * @Author: wujian
     * @Description: keyList 要是拼装好的 产品id_仓库id_batch_生产日期_保质期
     * @Date: 上午10:40 2022/1/18
     * @Param: [fixDataJobDTO, br]
     * @return: java.lang.String
     **/
    @RequestMapping(value = "/fixRedisStock", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixRedisStock(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> keyList = fixDataJobDTO.getKeyList();
        paasRedisHelper.removeStockValue(RedisPrefixConstant.PRODUCT_STOCK_LOCK,keyList);
        return "success";
    }


    /**
     * 修复工单出库出库数量
     *@Author: ruansicheng
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixOrderOutStockData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String cleanSettleAccounts(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = new ArrayList<>();
        //支持传入公司
        if (Objects.nonNull(fixDataJobDTO.getCorpidList()) && !fixDataJobDTO.getCorpidList().isEmpty()) {
            corpidList = fixDataJobDTO.getCorpidList();
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        //获取工单ID
        if (Objects.isNull(fixDataJobDTO.getDataIdList()) && fixDataJobDTO.getDataIdList().isEmpty()) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        List<Long> dataIds = fixDataJobDTO.getDataIdList();
        String corpid = corpidList.get(0);
        //获取工单
        Map<String, Object> param=new HashMap<>();
        param.put("ids",dataIds);
        param.put("del",0);
        param.put("corpid",corpid);
        List<WorkOrderEntity> workOrderEntities=workOrderModel.findEntitysWithoutSub(param);
        Map<Long,WorkOrderEntity> workOrderMap=new HashMap<>();
        workOrderEntities.forEach(item -> {
            workOrderMap.put(item.getId(),item);
        });
        long start = DateTimeUtil.getInt();
        LOG.warn("修复出库数量 begin。。。。。。。");

        //根据工单ID查询出所有工单关联产品数据
        //去更新的数据
        //是否完全出库
        Boolean allOutFlag=true;
        List<WorkOrderProductEntity> needUpdateList=new ArrayList<>();
        List<WorkOrderEntity> needUpdateOrderList=new ArrayList<>();
         for (Long dataId : dataIds) {
            List<WorkOrderProductEntity> workOrderProductEntities = workOrderProductModel.getProductsByWorkOrderId(dataId, corpid);
            //没有关联产品数据就跳过
            if (workOrderProductEntities.isEmpty()){
                continue;
            }
            //获取出库数量
            List<OutstockProductEntity> outstockProductEntities=outstockProductModel.getOrderOutStockData(dataId,corpid);
            if (!outstockProductEntities.isEmpty()){
                Map<Long,Double> outStockMap=new HashMap<>();
                outstockProductEntities.forEach(item -> {
                    outStockMap.put(item.getProductId(),item.getProductNum());
                });
                for (WorkOrderProductEntity workOrderProductEntity:workOrderProductEntities){
                    if (Objects.nonNull(outStockMap.get(workOrderProductEntity.getProductId()))){
                        workOrderProductEntity.setOutstockNum(outStockMap.get(workOrderProductEntity.getProductId()));
                        needUpdateList.add(workOrderProductEntity);
                    }
                    //判断一下是否出库完毕更新一下工单状态
                    if (workOrderProductEntity.getProductNum()>workOrderProductEntity.getOutstockNum()){
                        allOutFlag=false;
                    }
                }
                if (allOutFlag){
                    //去更新工单标志
                    WorkOrderEntity workOrderEntity=workOrderMap.get(dataId);
                    workOrderEntity.setAllOutbound(AllOutBoundEnum.ALL_OUT.getCode());
                    needUpdateOrderList.add(workOrderEntity);
                }
            }
        }
         if (!needUpdateList.isEmpty()){
             //批量更新
             workOrderProductModel.updateBatch(needUpdateList,corpid);
         }
        if (!needUpdateOrderList.isEmpty()){
            //批量更新工单
            workOrderModel.updateBatchList(needUpdateOrderList,corpid);
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("修复出库数量结束！");
        return "success";
    }


    /**
     * 修复bug：http://z.xbongbong.com/www/index.php?m=bug&f=view&bugID=49882
     * 迁移过来的refund数据，没有退货产品的时候，需要将标志改为【不需要入库】
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixRefund", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixRefund(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        long start = DateTimeUtil.getInt();

        // select count(1) from tb_saas_refund where corpid='ding6ec5ff4ec6eda4cb35c2f4657eb6378f' and del=0   =====>> 128条
        // ding6ec5ff4ec6eda4cb35c2f4657eb6378f 查了下这家公司一共128条数据

        String corpid = fixDataJobDTO.getCorpid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        Integer totalCount = refundModel.getEntitysCount(param);
        if (totalCount > 200) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, ">200暂不支持");
        }

        int i = 0;
        List<UpdateDataEntity> updateList = new ArrayList<>();
        List<RefundEntityExt> refundList = refundModel.findEntitys(param);
        for (RefundEntityExt refund : refundList) {
            LOG.info("fixRefund执行进度{}", ++i);
            JSONObject data = refund.getData();
            Long redContractId = data.getLong(RefundEnum.RED_CONTRACT_ID.getAttr());
            if (Objects.isNull(redContractId)) {
                continue;
            }
            param.put("contractId", redContractId);
            Integer productCount = contractProductModel.getEntitysCount(param);
            if (Objects.equals(productCount, 0)) {
                JSONObject updateData = new JSONObject();
                // 0:部分(未)入库 1：已入库完毕 2：不需要入库
                updateData.put(RefundEnum.ALL_IN_BOUND.getAttr(), 2);
                UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(refund.getId(), updateData, corpid, refund.getUpdateTime());
                updateList.add(updateDataEntity);
            }
        }
        if (CollectionsUtil.isNotEmpty(updateList)) {
            refundModel.updateBatch(updateList, corpid);
        }
        LOG.info("耗时{}", DateTimeUtil.getInt() - start);

        return "SUCCESS";
    }



    /**
     * 修复序列号错乱bug
     *
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixProductSerial", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixProductSerial(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        long start = DateTimeUtil.getInt();
        String corpid = fixDataJobDTO.getCorpid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("productId", fixDataJobDTO.getDataId());
        List<ProductSerialBalanceEntity> updateList = new ArrayList<>();
        List<ProductSerialBalanceEntity> productSerialBalanceList = productSerialBalanceModel.findEntitys(param);
        List<ProductSerialFlowEntity> productSerialFlowEntities = productSerialFlowModel.getLastSerialFlowByProductId(param);
        Map<String,ProductSerialFlowEntity> productSerialFlowMap=new HashMap<>();
        productSerialFlowEntities.forEach(item -> {
            productSerialFlowMap.put(item.getSeqKey(),item);
        });
        int i = 0;
        for (ProductSerialBalanceEntity productSerialBalanceEntity : productSerialBalanceList) {
            LOG.info("fixProductSerial执行进度{}", ++i);
            ProductSerialFlowEntity productSerialFlowEntity=productSerialFlowMap.get(productSerialBalanceEntity.getSeqKey());
            if (Objects.nonNull(productSerialFlowEntity)){
                //比较一下状态是否相同，不相同则异常
                if (!Objects.equals(productSerialBalanceEntity.getStatus(),productSerialFlowEntity.getStatus())
                || !Objects.equals(productSerialBalanceEntity.getBusinessType(),productSerialFlowEntity.getBusinessType())
                || !Objects.equals(productSerialBalanceEntity.getWarehouseId(),productSerialFlowEntity.getWarehouseId())){
                    productSerialBalanceEntity.setBusinessType(productSerialFlowEntity.getBusinessType());
                    productSerialBalanceEntity.setStatus(productSerialFlowEntity.getStatus());
                    productSerialBalanceEntity.setWarehouseId(productSerialFlowEntity.getWarehouseId());
                    updateList.add(productSerialBalanceEntity);
                }
            }
        }
        if (CollectionsUtil.isNotEmpty(updateList)) {
            productSerialBalanceModel.updateBatch(updateList, corpid);
        }
        LOG.info("耗时{}", DateTimeUtil.getInt() - start);
        return "SUCCESS";
    }

    @RequestMapping(value = "/fixContractOutstockStock", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContractOutstockStock(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (Objects.isNull(corpidList) || corpidList.size() != 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "只允许刷一个公司");
        }
        String corpid = corpidList.get(0);
        LOG.warn("fixContractOutstockStock 开始");
        //获取销售出库单数据
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("type", OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode());
        List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(param);
        //计算结存对比
        List<OutstockProductEntity> outstockProductList = new ArrayList<>();
        Map<Long, Double> totalMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (OutstockProductEntity item : outstockProductEntityList){
            JSONObject data = item.getData();
            Double nun = FastJsonHelper.getDoubleOrDefault(data, SelectProductEnum.NUM.getAttr(), BasicConstant.ZERO_DOUBLE);
            Double price = FastJsonHelper.getDoubleOrDefault(data, SelectProductEnum.SELLING_PRICE.getAttr(), BasicConstant.ZERO_DOUBLE);
            Double subTotal = FastJsonHelper.getDoubleOrDefault(data, SelectProductEnum.SUBTOTAL.getAttr(), BasicConstant.ZERO_DOUBLE);
            Double total = Arith.mul(nun, price);
            if (!Objects.equals(subTotal.compareTo(total) ,0)){
                data.put(SelectProductEnum.SUBTOTAL.getAttr(), total);
                outstockProductList.add(item);
            }
            //计算每个销售出库单的销售小计
            Double oldTotal = totalMap.get(item.getOutWarehouseId());
            if (Objects.isNull(oldTotal)){
                oldTotal = total;
            }else {
                oldTotal = Arith.add(oldTotal, total);
            }
            totalMap.put(item.getOutWarehouseId(), oldTotal);
        }
        //获取销售出库单
        PaasFormEntityExt paasFormEntityExt = paasFormModel.getByBusinessType(XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode(), corpid);
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        params.put(StringConstant.FORM_ID, paasFormEntityExt.getId());
        List<OutstockEntityExt> outstockEntityExtList = outstockModel.findEntitys(params);
        List<UpdateDataEntity> updateList = new ArrayList<>();
        outstockEntityExtList.forEach(item->{
            Double newTotal = totalMap.get(item.getId());
            if(Objects.nonNull(newTotal)) {
                JSONObject data = item.getData();
                Double oldTotal = FastJsonHelper.getDoubleOrDefault(data, ContractOutstockEnum.PRODUCT_TOTAL.getAttr(), BasicConstant.ZERO_DOUBLE);
                if (!Objects.equals(oldTotal.compareTo(newTotal), 0)) {
                    data.put(ContractOutstockEnum.PRODUCT_TOTAL.getAttr(), newTotal);
                    updateList.add(ExplainUtil.getUpdateData(item.getId(), data, corpid));
                }
            }
        });
        //更新销售出库产品表数据
        LOG.warn("总共有" + outstockProductList.size() + "条出库产品数据需要更新");
        if (CollectionsUtil.isNotEmpty(outstockProductList)){
            outstockProductModel.updateMulti(outstockProductList, corpid);
        }
        //更新销售出库单产品小计
        LOG.warn("总共有" + updateList.size() + "条销售出库单数据需要更新");
        if (CollectionsUtil.isNotEmpty(updateList)){
            outstockModel.updateBatch(updateList, corpid);
        }
        return "success";
    }

    /**
     * 修复合同异常导致可用库存量计算不准确脚本
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixAvailableStock", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixAvailableStock(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (Objects.isNull(corpidList) || corpidList.size() != 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "只允许刷一个公司");
        }
        String corpid = corpidList.get(0);
        LOG.warn("fixAvailableStock 开始");
        //获取合同产品关联表数据
        Long idGte = 0L;
        while (true) {
            // 拿出该公司下的所有未出库产品
            Map<String, Object> param = new HashMap<>();
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("idGte", idGte);
            param.put("status", 0);
            param.put("pageSize", 500);
            param.put("orderByStr", "id asc");
            List<ContractProductEntity> contractProductEntities = contractProductModel.findEntitys(param);
            if (contractProductEntities.isEmpty()) {
                break;
            }
            //每次查询出来最大的产品ID
            idGte = contractProductEntities.get(contractProductEntities.size() - 1).getId();
            //组装产品ID集合
            List<Long> contractIdList = new ArrayList<>();
            if (CollectionsUtil.isNotEmpty(contractProductEntities)) {
                contractProductEntities.forEach(item -> contractIdList.add(item.getContractId()));
            }
            //判断合同是否符合待出库状态
            List<SortBuilder> sortBuilders = new ArrayList<>();
            sortBuilders = Collections.singletonList(new FieldSortBuilder(ContractEnum.UPDATE_TIME.getAttr()).order(SortOrder.DESC));
            // 查询合同订单有产品 且出库状态不是全部出库且不是关闭的的 且未归档 更新时间倒序排序 del= 0
            BoolQueryBuilder contractBoolQueryBuilder = boolQuery();
            contractBoolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            contractBoolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_CONTRACT.getType()));
            contractBoolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            contractBoolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType(), FlowStatusEnum.IN_APPROVAL.getType(), FlowStatusEnum.APPROVAL_PENDING.getType())));
            contractBoolQueryBuilder.filter(termsQuery("id", contractIdList));
            // 限制返回值
            List<String> fieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias());
            List<ConditionsEntityExt> conditionList = new ArrayList<>();
            ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
            conditionsEntityExt.setAttr(ContractEnum.ALL_OUT_BOUND.getAttr());
            conditionsEntityExt.setFieldType(ContractEnum.ALL_OUT_BOUND.getFieldType());
            conditionsEntityExt.setSymbol(ConditionEnum.EQUAL.getSymbol());
            conditionsEntityExt.setValue(Collections.singletonList(0));
            ConditionsEntityExt shipConditionsEntityExt = new ConditionsEntityExt();
            shipConditionsEntityExt.setAttr(ContractEnum.SHIP_STATUS.getAttr());
            shipConditionsEntityExt.setFieldType(ContractEnum.SHIP_STATUS.getFieldType());
            shipConditionsEntityExt.setSymbol(ConditionEnum.NOEQUAL.getSymbol());
            shipConditionsEntityExt.setValue(Collections.singletonList(ShipStatusEnum.CLOSED.getCode()));
            ConditionsEntityExt arachivedEntityExt = new ConditionsEntityExt();
            arachivedEntityExt.setAttr(ContractEnum.ARCHIVED.getAttr());
            arachivedEntityExt.setFieldType(ContractEnum.ARCHIVED.getFieldType());
            arachivedEntityExt.setSymbol(ConditionEnum.EQUAL.getSymbol());
            arachivedEntityExt.setValue(Collections.singletonList(ArchivedEnum.UN_ARCHIVED.getCode()));
            ConditionsEntityExt redConditionsEntityExt = new ConditionsEntityExt();
            redConditionsEntityExt.setAttr(ContractEnum.IS_RED.getAttr());
            redConditionsEntityExt.setFieldType(ContractEnum.IS_RED.getFieldType());
            redConditionsEntityExt.setSymbol(ConditionEnum.EQUAL.getSymbol());
            redConditionsEntityExt.setValue(Collections.singletonList(0));
            ConditionsEntityExt productConditionsEntityExt = new ConditionsEntityExt();
            productConditionsEntityExt.setAttr(ContractEnum.PRODUCT.getAttr());
            productConditionsEntityExt.setFieldType(ContractEnum.PRODUCT.getFieldType());
            productConditionsEntityExt.setSymbol(ConditionEnum.NOEMPTY.getSymbol());
            conditionList.add(conditionsEntityExt);
            conditionList.add(productConditionsEntityExt);
            conditionList.add(arachivedEntityExt);
            conditionList.add(redConditionsEntityExt);
            conditionList.add(shipConditionsEntityExt);
            EsUtil.parseCondition(contractBoolQueryBuilder, conditionList, "", corpid, XbbRefTypeEnum.CONTRACT.getCode());
            //解析或条件
            XbbAggregatedPage<PaasFormDataEntityExt> byPage = esHelper.findByPage(IndexTypeEnum.IDX_SAAS_CONTRACT, contractBoolQueryBuilder, PaasFormDataEntityExt.class, fieldList,0,contractIdList.size(), sortBuilders);
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = byPage.getContent();
            List<Long> rightContractIds = new ArrayList<>();
            if (!paasFormDataEntityExtList.isEmpty()) {
                for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExtList) {
                    rightContractIds.add(paasFormDataEntityExt.getDataId());
                }
            }
            List<Long> contractIds = new ArrayList<>();
            for (Long id:contractIdList){
                if (!rightContractIds.contains(id)){
                    contractIds.add(id);
                }
            }
            if (CollectionsUtil.isNotEmpty(contractIds)){
                contractProductModel.updateWaitOutStatusById(contractIds, corpid, WaitOutStockStatusEnum.UNUSUAL.getCode(),BasicConstant.THREE);
            }
        }
        LOG.info("success");
        return "success";
    }
}